The process_deposit code below seems to work as follows.
If the deposit originates from a pubkey that is not in state.validators, a new entry is created and appended at the end of state.validators and initialised with the deposit. The corresponding state.balances entry is also updated.
However, if the pubkey of the deposit is in state.validators, say at index i, only the state.balances[i] is updated, not the state.validators[i].effective_balance.
Is it desirable that the following invariant holds: for all (Beacon) state s,
forall 0 <= i < s.validators.length, s.validators[i].effective_balance == s.balances[i]?
If yes it seems to be broken when a deposit is made by a validator that is already in state.validators. The last else statement updates the balances but not the corresponding BeaconState state.validators[i].effective_balance. increase_balance does not update the state.
Is it a bug or a feature?
Note: even when a new validator is created the balances is updated with the amount but the state is updated with amount - amount % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE), which are two different values.
Is this also a bug or a feature?
def process_deposit(state: BeaconState, deposit: Deposit) -> None:
# Verify the Merkle branch
assert is_valid_merkle_branch(
leaf=hash_tree_root(deposit.data),
branch=deposit.proof,
depth=DEPOSIT_CONTRACT_TREE_DEPTH + 1, # Add 1 for the `List` length mix-in
index=state.eth1_deposit_index,
root=state.eth1_data.deposit_root,
)
# Deposits must be processed in order
state.eth1_deposit_index += 1
pubkey = deposit.data.pubkey
amount = deposit.data.amount
validator_pubkeys = [v.pubkey for v in state.validators]
if pubkey not in validator_pubkeys:
# Verify the deposit signature (proof of possession) for new validators.
# Note: The deposit contract does not check signatures.
# Note: Deposits are valid across forks, thus the deposit domain is retrieved directly from `compute_domain`.
domain = compute_domain(DOMAIN_DEPOSIT)
deposit_message = DepositMessage(
pubkey=deposit.data.pubkey,
withdrawal_credentials=deposit.data.withdrawal_credentials,
amount=deposit.data.amount)
if not bls_verify(pubkey, hash_tree_root(deposit_message), deposit.data.signature, domain):
return
# Add validator and balance entries
state.validators.append(Validator(
pubkey=pubkey,
withdrawal_credentials=deposit.data.withdrawal_credentials,
activation_eligibility_epoch=FAR_FUTURE_EPOCH,
activation_epoch=FAR_FUTURE_EPOCH,
exit_epoch=FAR_FUTURE_EPOCH,
withdrawable_epoch=FAR_FUTURE_EPOCH,
effective_balance=min(amount - amount % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE),
))
state.balances.append(amount)
else:
# Increase balance by deposit amount
index = ValidatorIndex(validator_pubkeys.index(pubkey))
increase_balance(state, index, amount)
The process_deposit code below seems to work as follows.
If the deposit originates from a pubkey that is not in
state.validators, a new entry is created and appended at the end ofstate.validatorsand initialised with the deposit. The corresponding state.balances entry is also updated.However, if the pubkey of the deposit is in
state.validators, say at index i, only thestate.balances[i]is updated, not thestate.validators[i].effective_balance.Is it desirable that the following invariant holds: for all (Beacon) state s,
forall 0 <= i < s.validators.length, s.validators[i].effective_balance == s.balances[i]?If yes it seems to be broken when a deposit is made by a validator that is already in
state.validators. The last else statement updates the balances but not the corresponding BeaconStatestate.validators[i].effective_balance.increase_balancedoes not update the state.Is it a bug or a feature?
Note: even when a new validator is created the balances is updated with the
amountbut the state is updated withamount - amount % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE),which are two different values.Is this also a bug or a feature?