def process_deposit(state: BeaconState, deposit: Deposit, slots_per_epoch: int, deposit_contract_tree_depth: int) -> BeaconState: """ Process a deposit from Ethereum 1.0. """ validate_deposit(state, deposit, deposit_contract_tree_depth) # Increment the next deposit index we are expecting. Note that this # needs to be done here because while the deposit contract will never # create an invalid Merkle branch, it may admit an invalid deposit # object, and we need to be able to skip over it state = state.copy(deposit_index=state.deposit_index + 1, ) validator_pubkeys = tuple(v.pubkey for v in state.validator_registry) deposit_input = deposit.deposit_data.deposit_input pubkey = deposit_input.pubkey amount = deposit.deposit_data.amount withdrawal_credentials = deposit_input.withdrawal_credentials if pubkey not in validator_pubkeys: # Verify the proof of possession proof_is_valid = bls.verify( pubkey=pubkey, message_hash=deposit_input.signed_root, signature=deposit_input.proof_of_possession, domain=get_domain( state.fork, state.current_epoch(slots_per_epoch), SignatureDomain.DOMAIN_DEPOSIT, ), ) if not proof_is_valid: return state validator = ValidatorRecord.create_pending_validator( pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, ) # Note: In phase 2 registry indices that has been withdrawn for a long time # will be recycled. state = add_pending_validator( state, validator, amount, ) else: # Top-up - increase balance by deposit index = ValidatorIndex(validator_pubkeys.index(pubkey)) validator = state.validator_registry[index] # Update validator's balance and state state = state.update_validator_balance( validator_index=index, balance=state.validator_balances[index] + amount, ) return state
def process_deposit(*, state: BeaconState, pubkey: BLSPubkey, amount: Gwei, proof_of_possession: BLSSignature, withdrawal_credentials: Hash32, randao_commitment: Hash32, custody_commitment: Hash32, epoch_length: int) -> BeaconState: """ Process a deposit from Ethereum 1.0. """ validate_proof_of_possession( state=state, pubkey=pubkey, proof_of_possession=proof_of_possession, withdrawal_credentials=withdrawal_credentials, randao_commitment=randao_commitment, custody_commitment=custody_commitment, epoch_length=epoch_length, ) validator_pubkeys = tuple(v.pubkey for v in state.validator_registry) if pubkey not in validator_pubkeys: validator = ValidatorRecord.create_pending_validator( pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, randao_commitment=randao_commitment, custody_commitment=custody_commitment, ) # Note: In phase 2 registry indices that has been withdrawn for a long time # will be recycled. state = add_pending_validator( state, validator, amount, ) else: # Top-up - increase balance by deposit index = ValidatorIndex(validator_pubkeys.index(pubkey)) validator = state.validator_registry[index] if validator.withdrawal_credentials != withdrawal_credentials: raise ValidationError("`withdrawal_credentials` are incorrect:\n" "\texpected: %s, found: %s" % ( validator.withdrawal_credentials, validator.withdrawal_credentials, )) # Update validator's balance and state state = state.update_validator_balance( validator_index=index, balance=state.validator_balances[index] + amount, ) return state
def test_create_pending_validator(): pubkey = 123 withdrawal_credentials = b'\x11' * 32 validator = ValidatorRecord.create_pending_validator( pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, ) assert validator.pubkey == pubkey assert validator.withdrawal_credentials == withdrawal_credentials assert validator.activation_epoch == FAR_FUTURE_EPOCH assert validator.exit_epoch == FAR_FUTURE_EPOCH assert validator.initiated_exit is False assert validator.slashed is False
def test_create_pending_validator(): pubkey = 123 withdrawal_credentials = b'\x11' * 32 randao_commitment = b'\x22' * 32 validator = ValidatorRecord.create_pending_validator( pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, randao_commitment=randao_commitment, ) assert validator.pubkey == pubkey assert validator.withdrawal_credentials == withdrawal_credentials assert validator.randao_commitment == randao_commitment assert validator.randao_layers == 0 assert validator.activation_epoch == FAR_FUTURE_EPOCH assert validator.exit_epoch == FAR_FUTURE_EPOCH assert validator.withdrawal_epoch == FAR_FUTURE_EPOCH assert validator.penalized_epoch == FAR_FUTURE_EPOCH
def test_create_pending_validator(): pubkey = 123 withdrawal_credentials = b'\x11' * 32 randao_commitment = b'\x22' * 32 custody_commitment = b'\x33' * 32 validator = ValidatorRecord.create_pending_validator( pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, randao_commitment=randao_commitment, custody_commitment=custody_commitment, ) assert validator.pubkey == pubkey assert validator.withdrawal_credentials == withdrawal_credentials assert validator.randao_commitment == randao_commitment assert validator.randao_layers == 0 assert validator.activation_slot == FAR_FUTURE_SLOT assert validator.exit_slot == FAR_FUTURE_SLOT assert validator.withdrawal_slot == FAR_FUTURE_SLOT assert validator.penalized_slot == FAR_FUTURE_SLOT assert validator.exit_count == 0
def test_update_validator_registry(n, n_validators_state, config, slots_per_epoch): validator_registry = list(n_validators_state.validator_registry) activating_index = n exiting_index = 0 activating_validator = ValidatorRecord.create_pending_validator( pubkey=b'\x10' * 48, withdrawal_credentials=b'\x11' * 32, ) exiting_validator = n_validators_state.validator_registry[exiting_index].copy( exit_epoch=FAR_FUTURE_EPOCH, initiated_exit=True, ) validator_registry[exiting_index] = exiting_validator validator_registry.append(activating_validator) state = n_validators_state.copy( validator_registry=validator_registry, validator_balances=n_validators_state.validator_balances + (config.MAX_DEPOSIT_AMOUNT,), ) state = update_validator_registry(state, config) entry_exit_effect_epoch = get_delayed_activation_exit_epoch( state.current_epoch(slots_per_epoch), config.ACTIVATION_EXIT_DELAY, ) # Check if the activating_validator is activated assert state.validator_registry[activating_index].activation_epoch == entry_exit_effect_epoch # Check if the activating_validator is exited assert state.validator_registry[exiting_index].exit_epoch == entry_exit_effect_epoch