def test_process_deposit(config, deposit_contract_tree_depth, sample_beacon_state_params, keymap, pubkeys): validator_index = 0 withdrawal_credentials = b'\x34' * 32 state, deposit = create_mock_deposit( config, sample_beacon_state_params, keymap, pubkeys, withdrawal_credentials, validator_index, ) # Add the first validator result_state = process_deposit( state=state, deposit=deposit, slots_per_epoch=config.SLOTS_PER_EPOCH, deposit_contract_tree_depth=deposit_contract_tree_depth, ) assert len(result_state.validator_registry) == 1 validator = result_state.validator_registry[validator_index] assert validator.pubkey == pubkeys[validator_index] assert validator.withdrawal_credentials == withdrawal_credentials assert result_state.validator_balances[ validator_index] == config.MAX_DEPOSIT_AMOUNT # test immutable assert len(state.validator_registry) == 0
def process_deposits(state: BeaconState, block: BaseBeaconBlock, config: Eth2Config) -> BeaconState: if len(block.body.deposits) > config.MAX_DEPOSITS: raise ValidationError(f"The block ({block}) has too many deposits:\n" f"\tFound {len(block.body.deposits)} deposits, " f"maximum: {config.MAX_DEPOSITS}") for deposit in block.body.deposits: state = process_deposit(state, deposit, config) return state
def is_genesis_trigger(deposits: Sequence[Deposit], timestamp: int, config: Eth2Config) -> bool: state = BeaconState(config=config) for deposit in deposits: state = process_deposit(state, deposit, config) active_validator_count = 0 for validator in state.validators: if validator.effective_balance == config.MAX_EFFECTIVE_BALANCE: active_validator_count += 1 return active_validator_count == config.GENESIS_ACTIVE_VALIDATOR_COUNT
def initialize_beacon_state_from_eth1(*, eth1_block_hash: Hash32, eth1_timestamp: Timestamp, deposits: Sequence[Deposit], config: Eth2Config) -> BeaconState: fork = Fork.create( previous_version=config.GENESIS_FORK_VERSION, current_version=config.GENESIS_FORK_VERSION, epoch=GENESIS_EPOCH, ) state = BeaconState.create( genesis_time=_genesis_time_from_eth1_timestamp(eth1_timestamp, config.GENESIS_DELAY), fork=fork, eth1_data=Eth1Data.create(block_hash=eth1_block_hash, deposit_count=len(deposits)), latest_block_header=BeaconBlockHeader.create( body_root=BeaconBlockBody.create().hash_tree_root), block_roots=(ZERO_ROOT, ) * config.SLOTS_PER_HISTORICAL_ROOT, state_roots=(ZERO_HASH32, ) * config.SLOTS_PER_HISTORICAL_ROOT, randao_mixes=(eth1_block_hash, ) * config.EPOCHS_PER_HISTORICAL_VECTOR, slashings=(Gwei(0), ) * config.EPOCHS_PER_SLASHINGS_VECTOR, config=config, ) # Process genesis deposits for index, deposit in enumerate(deposits): deposit_data_list = tuple(deposit.data for deposit in deposits[:index + 1]) deposit_root = ssz.get_hash_tree_root( deposit_data_list, ssz.List(DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH)) state = state.transform(("eth1_data", "deposit_root"), deposit_root) state = process_deposit(state=state, deposit=deposit, config=config) # Process genesis activations for validator_index in range(len(state.validators)): validator_index = ValidatorIndex(validator_index) balance = state.balances[validator_index] effective_balance = calculate_effective_balance(balance, config) state = state.transform( ("validators", validator_index, "effective_balance"), effective_balance) if effective_balance == config.MAX_EFFECTIVE_BALANCE: activated_validator = activate_validator( state.validators[validator_index], GENESIS_EPOCH) state = state.transform(("validators", validator_index), activated_validator) return state.set("genesis_validators_root", state.validators.hash_tree_root)
def FuzzerRunOne(input_data: bytes) -> typing.Optional[bytes]: test_case = ssz.decode(input_data, sedes=DepositTestCase) # TODO(gnattishness) any other relevant exceptions to catch? try: post = process_deposit( state=test_case.pre, deposit=test_case.deposit, config=SERENITY_CONFIG, ) except ValidationError: return None return ssz.encode(post)
def process_deposits(state: BeaconState, block: BaseBeaconBlock, config: Eth2Config) -> BeaconState: if len(block.body.deposits) > config.MAX_DEPOSITS: raise ValidationError(f"The block ({block}) has too many deposits:\n" f"\tFound {len(block.body.deposits)} deposits, " f"maximum: {config.MAX_DEPOSITS}") for deposit in block.body.deposits: state = process_deposit( state, deposit, slots_per_epoch=config.SLOTS_PER_EPOCH, deposit_contract_tree_depth=config.DEPOSIT_CONTRACT_TREE_DEPTH, ) return state
def test_process_deposit(config, sample_beacon_state_params, keymap, genesis_state, validator_count, is_new_validator, pubkeys): state = genesis_state withdrawal_credentials = b'\x34' * 32 if is_new_validator: validator_index = validator_count else: validator_index = validator_count - 1 pubkey = pubkeys[validator_index] state, deposit = create_mock_deposit( state, pubkey, keymap, withdrawal_credentials, config, ) validator_count_before_deposit = state.validator_count result_state = process_deposit( state=state, deposit=deposit, config=config, ) # test immutability assert len(state.validators) == validator_count_before_deposit validator = result_state.validators[validator_index] if is_new_validator: assert len(result_state.validators) == len(state.validators) + 1 assert validator.pubkey == pubkeys[validator_index] assert validator.withdrawal_credentials == withdrawal_credentials assert result_state.balances[ validator_index] == config.MAX_EFFECTIVE_BALANCE else: assert len(result_state.validators) == len(state.validators) assert validator.pubkey == pubkeys[validator_index] assert result_state.balances[ validator_index] == 2 * config.MAX_EFFECTIVE_BALANCE
def initialize_beacon_state_from_eth1(*, eth1_block_hash: Hash32, eth1_timestamp: Timestamp, deposits: Sequence[Deposit], config: Eth2Config) -> BeaconState: state = BeaconState( genesis_time=_genesis_time_from_eth1_timestamp(eth1_timestamp), eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=len(deposits)), latest_block_header=BeaconBlockHeader( body_root=BeaconBlockBody().hash_tree_root), randao_mixes=(eth1_block_hash, ) * config.EPOCHS_PER_HISTORICAL_VECTOR, config=config, ) # Process genesis deposits for index, deposit in enumerate(deposits): deposit_data_list = tuple(deposit.data for deposit in deposits[:index + 1]) state = state.copy(eth1_data=state.eth1_data.copy( deposit_root=ssz.get_hash_tree_root( deposit_data_list, ssz.List(DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH), ))) state = process_deposit(state=state, deposit=deposit, config=config) # Process genesis activations for validator_index in range(len(state.validators)): validator_index = ValidatorIndex(validator_index) balance = state.balances[validator_index] effective_balance = calculate_effective_balance(balance, config) state = state.update_validator_with_fn( validator_index, lambda v, *_: v.copy(effective_balance=effective_balance)) if effective_balance == config.MAX_EFFECTIVE_BALANCE: state = state.update_validator_with_fn(validator_index, activate_validator, config.GENESIS_EPOCH) return state
def get_genesis_beacon_state(*, genesis_deposits: Sequence[Deposit], genesis_time: Timestamp, genesis_eth1_data: Eth1Data, config: Eth2Config) -> BeaconState: state = BeaconState( genesis_time=genesis_time, eth1_data=genesis_eth1_data, latest_block_header=BeaconBlockHeader( body_root=BeaconBlockBody().root, ), config=config, ) # Process genesis deposits for deposit in genesis_deposits: state = process_deposit( state=state, deposit=deposit, config=config, ) # Process genesis activations for validator_index in range(len(state.validators)): validator_index = ValidatorIndex(validator_index) effective_balance = state.validators[validator_index].effective_balance is_enough_effective_balance = effective_balance >= config.MAX_EFFECTIVE_BALANCE if is_enough_effective_balance: state = state.update_validator_with_fn( validator_index, activate_validator, config.GENESIS_EPOCH, ) return genesis_state_with_active_index_roots( state, config, )
def test_process_deposit(epoch_length, sample_beacon_state_params, privkeys, pubkeys, max_deposit_amount): state = BeaconState(**sample_beacon_state_params).copy( slot=1, validator_registry=(), ) privkey_1 = privkeys[0] pubkey_1 = pubkeys[0] amount = max_deposit_amount withdrawal_credentials = b'\x34' * 32 custody_commitment = b'\x11' * 32 randao_commitment = b'\x56' * 32 deposit_input = DepositInput( pubkey=pubkey_1, withdrawal_credentials=withdrawal_credentials, randao_commitment=randao_commitment, custody_commitment=custody_commitment, ) proof_of_possession = sign_proof_of_possession( deposit_input, privkey_1, state.fork, state.slot, epoch_length, ) # Add the first validator result_state = process_deposit( state=state, pubkey=pubkey_1, amount=amount, proof_of_possession=proof_of_possession, withdrawal_credentials=withdrawal_credentials, randao_commitment=randao_commitment, custody_commitment=custody_commitment, epoch_length=epoch_length, ) assert len(result_state.validator_registry) == 1 index = 0 assert result_state.validator_registry[0].pubkey == pubkey_1 assert result_state.validator_registry[ index].withdrawal_credentials == withdrawal_credentials assert result_state.validator_registry[ index].randao_commitment == randao_commitment assert result_state.validator_balances[index] == amount # test immutable assert len(state.validator_registry) == 0 # Add the second validator privkey_2 = privkeys[1] pubkey_2 = pubkeys[1] deposit_input = DepositInput( pubkey=pubkey_2, withdrawal_credentials=withdrawal_credentials, randao_commitment=randao_commitment, custody_commitment=custody_commitment, ) proof_of_possession = sign_proof_of_possession( deposit_input, privkey_2, state.fork, state.slot, epoch_length, ) result_state = process_deposit( state=result_state, pubkey=pubkey_2, amount=amount, proof_of_possession=proof_of_possession, withdrawal_credentials=withdrawal_credentials, randao_commitment=randao_commitment, custody_commitment=custody_commitment, epoch_length=epoch_length, ) assert len(result_state.validator_registry) == 2 assert result_state.validator_registry[1].pubkey == pubkey_2
def get_genesis_beacon_state(*, genesis_validator_deposits: Sequence[Deposit], genesis_time: Timestamp, latest_eth1_data: Eth1Data, genesis_slot: SlotNumber, genesis_epoch: EpochNumber, genesis_fork_version: int, genesis_start_shard: ShardNumber, shard_count: int, seed_lookahead: int, latest_block_roots_length: int, latest_index_roots_length: int, epoch_length: int, max_deposit_amount: Gwei, latest_penalized_exit_length: int, latest_randao_mixes_length: int, entry_exit_delay: int) -> BeaconState: state = BeaconState( # Misc slot=genesis_slot, genesis_time=genesis_time, fork=Fork( previous_version=genesis_fork_version, current_version=genesis_fork_version, epoch=genesis_epoch, ), # Validator registry validator_registry=(), validator_balances=(), validator_registry_update_epoch=genesis_epoch, # Randomness and committees latest_randao_mixes=(ZERO_HASH32,) * latest_randao_mixes_length, previous_epoch_start_shard=genesis_start_shard, current_epoch_start_shard=genesis_start_shard, previous_calculation_epoch=genesis_epoch, current_calculation_epoch=genesis_epoch, previous_epoch_seed=ZERO_HASH32, current_epoch_seed=ZERO_HASH32, # Finality previous_justified_epoch=genesis_epoch, justified_epoch=genesis_epoch, justification_bitfield=0, finalized_epoch=genesis_epoch, # Recent state latest_crosslinks=( (CrosslinkRecord(epoch=genesis_epoch, shard_block_root=ZERO_HASH32),) * shard_count ), latest_block_roots=(ZERO_HASH32,) * latest_block_roots_length, latest_index_roots=(ZERO_HASH32,) * latest_index_roots_length, latest_penalized_balances=(Gwei(0),) * latest_penalized_exit_length, latest_attestations=(), batched_block_roots=(), # Ethereum 1.0 chain data latest_eth1_data=latest_eth1_data, eth1_data_votes=(), deposit_index=len(genesis_validator_deposits), ) # Process initial deposits for deposit in genesis_validator_deposits: state = process_deposit( state=state, pubkey=deposit.deposit_data.deposit_input.pubkey, amount=deposit.deposit_data.amount, proof_of_possession=deposit.deposit_data.deposit_input.proof_of_possession, withdrawal_credentials=deposit.deposit_data.deposit_input.withdrawal_credentials, epoch_length=epoch_length, ) # Process initial activations for validator_index, _ in enumerate(state.validator_registry): validator_index = ValidatorIndex(validator_index) is_enough_effective_balance = get_effective_balance( state.validator_balances, validator_index, max_deposit_amount, ) >= max_deposit_amount if is_enough_effective_balance: state = activate_validator( state=state, index=validator_index, is_genesis=True, genesis_epoch=genesis_epoch, epoch_length=epoch_length, entry_exit_delay=entry_exit_delay, ) # TODO: chanege to hash_tree_root active_validator_indices = get_active_validator_indices( state.validator_registry, genesis_epoch, ) genesis_active_index_root = hash_eth2( b''.join( [ index.to_bytes(32, 'big') for index in active_validator_indices ] ) ) latest_index_roots = (genesis_active_index_root,) * latest_index_roots_length state = state.copy( latest_index_roots=latest_index_roots, ) current_epoch_seed = generate_seed( state=state, epoch=genesis_epoch, epoch_length=epoch_length, seed_lookahead=seed_lookahead, entry_exit_delay=entry_exit_delay, latest_index_roots_length=latest_index_roots_length, latest_randao_mixes_length=latest_randao_mixes_length, ) state = state.copy( current_epoch_seed=current_epoch_seed, ) return state
def get_genesis_beacon_state( *, genesis_validator_deposits: Sequence[Deposit], genesis_time: Timestamp, genesis_eth1_data: Eth1Data, genesis_slot: Slot, genesis_epoch: Epoch, genesis_fork_version: int, genesis_start_shard: Shard, shard_count: int, min_seed_lookahead: int, slots_per_historical_root: int, latest_active_index_roots_length: int, slots_per_epoch: int, max_deposit_amount: Gwei, latest_slashed_exit_length: int, latest_randao_mixes_length: int, activation_exit_delay: int, deposit_contract_tree_depth: int, block_class: Type[BaseBeaconBlock]) -> BeaconState: state = BeaconState( # Misc slot=genesis_slot, genesis_time=genesis_time, fork=Fork( previous_version=genesis_fork_version.to_bytes(4, 'little'), current_version=genesis_fork_version.to_bytes(4, 'little'), epoch=genesis_epoch, ), # Validator registry validator_registry=(), validator_balances=(), validator_registry_update_epoch=genesis_epoch, # Randomness and committees latest_randao_mixes=(ZERO_HASH32, ) * latest_randao_mixes_length, previous_shuffling_start_shard=genesis_start_shard, current_shuffling_start_shard=genesis_start_shard, previous_shuffling_epoch=genesis_epoch, current_shuffling_epoch=genesis_epoch, previous_shuffling_seed=ZERO_HASH32, current_shuffling_seed=ZERO_HASH32, # Finality previous_epoch_attestations=(), current_epoch_attestations=(), previous_justified_epoch=genesis_epoch, current_justified_epoch=genesis_epoch, previous_justified_root=ZERO_HASH32, current_justified_root=ZERO_HASH32, justification_bitfield=0, finalized_epoch=genesis_epoch, finalized_root=ZERO_HASH32, # Recent state latest_crosslinks=((CrosslinkRecord( epoch=genesis_epoch, crosslink_data_root=ZERO_HASH32), ) * shard_count), latest_block_roots=(ZERO_HASH32, ) * slots_per_historical_root, latest_state_roots=(ZERO_HASH32, ) * slots_per_historical_root, latest_active_index_roots=(ZERO_HASH32, ) * latest_active_index_roots_length, latest_slashed_balances=(Gwei(0), ) * latest_slashed_exit_length, latest_block_header=get_temporary_block_header( BeaconBlock.create_empty_block(genesis_slot), ), historical_roots=(), # Ethereum 1.0 chain data latest_eth1_data=genesis_eth1_data, eth1_data_votes=(), deposit_index=0, ) # Process genesis deposits for deposit in genesis_validator_deposits: state = process_deposit( state=state, deposit=deposit, slots_per_epoch=slots_per_epoch, deposit_contract_tree_depth=deposit_contract_tree_depth, ) # Process genesis activations for validator_index, _ in enumerate(state.validator_registry): validator_index = ValidatorIndex(validator_index) is_enough_effective_balance = get_effective_balance( state.validator_balances, validator_index, max_deposit_amount, ) >= max_deposit_amount if is_enough_effective_balance: state = activate_validator( state=state, index=validator_index, is_genesis=True, genesis_epoch=genesis_epoch, slots_per_epoch=slots_per_epoch, activation_exit_delay=activation_exit_delay, ) # TODO: chanege to hash_tree_root active_validator_indices = get_active_validator_indices( state.validator_registry, genesis_epoch, ) genesis_active_index_root = hash_eth2(b''.join( [index.to_bytes(32, 'little') for index in active_validator_indices])) latest_active_index_roots = ( genesis_active_index_root, ) * latest_active_index_roots_length state = state.copy(latest_active_index_roots=latest_active_index_roots, ) current_shuffling_seed = generate_seed( state=state, epoch=genesis_epoch, slots_per_epoch=slots_per_epoch, min_seed_lookahead=min_seed_lookahead, activation_exit_delay=activation_exit_delay, latest_active_index_roots_length=latest_active_index_roots_length, latest_randao_mixes_length=latest_randao_mixes_length, ) state = state.copy(current_shuffling_seed=current_shuffling_seed, ) return state
def get_initial_beacon_state(*, initial_validator_deposits: Sequence[Deposit], genesis_time: Timestamp, latest_eth1_data: Eth1Data, genesis_slot: SlotNumber, genesis_fork_version: int, genesis_start_shard: ShardNumber, shard_count: int, latest_block_roots_length: int, epoch_length: int, target_committee_size: int, max_deposit: Ether, latest_penalized_exit_length: int, latest_randao_mixes_length: int, entry_exit_delay: int) -> BeaconState: state = BeaconState( # Misc slot=genesis_slot, genesis_time=genesis_time, fork=Fork( previous_version=genesis_fork_version, current_version=genesis_fork_version, slot=genesis_slot, ), # Validator registry validator_registry=(), validator_balances=(), validator_registry_update_slot=genesis_slot, validator_registry_exit_count=0, validator_registry_delta_chain_tip=ZERO_HASH32, # Randomness and committees latest_randao_mixes=tuple(ZERO_HASH32 for _ in range(latest_randao_mixes_length)), latest_vdf_outputs=tuple(ZERO_HASH32 for _ in range(latest_randao_mixes_length // epoch_length)), # TODO Remove `persistent_committees`, `persistent_committee_reassignments` persistent_committees=(), persistent_committee_reassignments=(), previous_epoch_start_shard=genesis_start_shard, current_epoch_start_shard=genesis_start_shard, previous_epoch_calculation_slot=genesis_slot, current_epoch_calculation_slot=genesis_slot, previous_epoch_randao_mix=ZERO_HASH32, current_epoch_randao_mix=ZERO_HASH32, # Custody challenges custody_challenges=(), # Finality previous_justified_slot=genesis_slot, justified_slot=genesis_slot, justification_bitfield=0, finalized_slot=genesis_slot, # Recent state latest_crosslinks=tuple([ CrosslinkRecord(slot=genesis_slot, shard_block_root=ZERO_HASH32) for _ in range(shard_count) ]), latest_block_roots=tuple(ZERO_HASH32 for _ in range(latest_block_roots_length)), latest_penalized_balances=tuple( Gwei(0) for _ in range(latest_penalized_exit_length)), latest_attestations=(), batched_block_roots=(), # Ethereum 1.0 chain data latest_eth1_data=latest_eth1_data, eth1_data_votes=(), ) # Process initial deposits for deposit in initial_validator_deposits: state = process_deposit( state=state, pubkey=deposit.deposit_data.deposit_input.pubkey, amount=deposit.deposit_data.amount, proof_of_possession=deposit.deposit_data.deposit_input. proof_of_possession, withdrawal_credentials=deposit.deposit_data.deposit_input. withdrawal_credentials, randao_commitment=deposit.deposit_data.deposit_input. randao_commitment, custody_commitment=deposit.deposit_data.deposit_input. custody_commitment, ) for validator_index, _ in enumerate(state.validator_registry): validator_index = ValidatorIndex(validator_index) is_enough_effective_balance = get_effective_balance( state.validator_balances, validator_index, max_deposit, ) >= max_deposit * GWEI_PER_ETH if is_enough_effective_balance: state = activate_validator( state, validator_index, genesis=True, genesis_slot=genesis_slot, entry_exit_delay=entry_exit_delay, ) return state