def create_deposit_data(*, config: Eth2Config, pubkey: BLSPubkey, privkey: int, withdrawal_credentials: Hash32, fork: Fork, deposit_timestamp: Timestamp, amount: Gwei = None) -> DepositData: if amount is None: amount = config.MAX_DEPOSIT_AMOUNT return DepositData( deposit_input=DepositInput( pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, proof_of_possession=sign_proof_of_possession( deposit_input=DepositInput( pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, ), privkey=privkey, fork=fork, slot=config.GENESIS_SLOT, slots_per_epoch=config.SLOTS_PER_EPOCH, ), ), amount=amount, timestamp=deposit_timestamp, )
def create_mock_initial_validator_deposits( num_validators: int, config: BeaconConfig, pubkeys: Sequence[BLSPubkey], keymap: Dict[BLSPubkey, int]) -> Tuple[Deposit, ...]: # Mock data withdrawal_credentials = b'\x22' * 32 randao_commitment = b'\x33' * 32 custody_commitment = b'\x44' * 32 deposit_timestamp = 0 fork = Fork( previous_version=config.GENESIS_FORK_VERSION, current_version=config.GENESIS_FORK_VERSION, epoch=config.GENESIS_EPOCH, ) initial_validator_deposits = tuple( Deposit( branch=( b'\x11' * 32 for j in range(10) ), index=i, deposit_data=DepositData( deposit_input=DepositInput( pubkey=pubkeys[i], withdrawal_credentials=withdrawal_credentials, randao_commitment=randao_commitment, custody_commitment=custody_commitment, proof_of_possession=sign_proof_of_possession( deposit_input=DepositInput( pubkey=pubkeys[i], withdrawal_credentials=withdrawal_credentials, randao_commitment=randao_commitment, custody_commitment=custody_commitment, ), privkey=keymap[pubkeys[i]], fork=fork, slot=config.GENESIS_SLOT, epoch_length=config.EPOCH_LENGTH, ), ), amount=config.MAX_DEPOSIT_AMOUNT, timestamp=deposit_timestamp, ), ) for i in range(num_validators) ) return initial_validator_deposits
def validate_proof_of_possession(state: BeaconState, pubkey: BLSPubkey, proof_of_possession: BLSSignature, withdrawal_credentials: Hash32, randao_commitment: Hash32, custody_commitment: Hash32) -> None: deposit_input = DepositInput( pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, randao_commitment=randao_commitment, custody_commitment=custody_commitment, proof_of_possession=EMPTY_SIGNATURE, ) is_valid_signature = bls.verify( pubkey=pubkey, # TODO: change to hash_tree_root(deposit_input) when we have SSZ tree hashing message=deposit_input.root, signature=proof_of_possession, domain=get_domain( state.fork_data, state.slot, SignatureDomain.DOMAIN_DEPOSIT, ), ) if not is_valid_signature: raise ValidationError("BLS signature verification error")
def make_deposit_input(pubkey, withdrawal_credentials, randao_commitment, custody_commitment): return DepositInput( pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, randao_commitment=randao_commitment, custody_commitment=custody_commitment, proof_of_possession=EMPTY_SIGNATURE, )
def create_mock_genesis_validator_deposits( num_validators: int, config: BeaconConfig, pubkeys: Sequence[BLSPubkey], keymap: Dict[BLSPubkey, int]) -> Tuple[Deposit, ...]: # Mock data withdrawal_credentials = Hash32(b'\x22' * 32) deposit_timestamp = Timestamp(0) fork = Fork( previous_version=config.GENESIS_FORK_VERSION, current_version=config.GENESIS_FORK_VERSION, epoch=config.GENESIS_EPOCH, ) genesis_validator_deposits = tuple( Deposit( branch=tuple( Hash32(b'\x11' * 32) for j in range(10) ), index=i, deposit_data=DepositData( deposit_input=DepositInput( pubkey=pubkeys[i], withdrawal_credentials=withdrawal_credentials, proof_of_possession=sign_proof_of_possession( deposit_input=DepositInput( pubkey=pubkeys[i], withdrawal_credentials=withdrawal_credentials, ), privkey=keymap[pubkeys[i]], fork=fork, slot=config.GENESIS_SLOT, slots_per_epoch=config.SLOTS_PER_EPOCH, ), ), amount=config.MAX_DEPOSIT_AMOUNT, timestamp=deposit_timestamp, ), ) for i in range(num_validators) ) return genesis_validator_deposits
def test_validate_proof_of_possession(epoch_length, sample_beacon_state_params, pubkeys, privkeys, expected): state = BeaconState(**sample_beacon_state_params) privkey = privkeys[0] pubkey = pubkeys[0] withdrawal_credentials = b'\x34' * 32 custody_commitment = b'\x12' * 32 randao_commitment = b'\x56' * 32 deposit_input = DepositInput( pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, randao_commitment=randao_commitment, custody_commitment=custody_commitment, ) if expected is True: proof_of_possession = sign_proof_of_possession( deposit_input, privkey, state.fork, state.slot, epoch_length, ) 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, ) else: proof_of_possession = b'\x11' * 96 with pytest.raises(ValidationError): 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, )
def test_validate_proof_of_possession( slots_per_epoch, sample_beacon_state_params, pubkeys, privkeys, expected): state = BeaconState(**sample_beacon_state_params) privkey = privkeys[0] pubkey = pubkeys[0] withdrawal_credentials = b'\x34' * 32 deposit_input = DepositInput( pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, ) if expected is True: proof_of_possession = sign_proof_of_possession( deposit_input, privkey, state.fork, state.slot, slots_per_epoch, ) validate_proof_of_possession( state=state, pubkey=pubkey, proof_of_possession=proof_of_possession, withdrawal_credentials=withdrawal_credentials, slots_per_epoch=slots_per_epoch, ) else: proof_of_possession = b'\x11' * 96 with pytest.raises(ValidationError): validate_proof_of_possession( state=state, pubkey=pubkey, proof_of_possession=proof_of_possession, withdrawal_credentials=withdrawal_credentials, slots_per_epoch=slots_per_epoch, )
def validate_proof_of_possession(state: BeaconState, pubkey: BLSPubkey, proof_of_possession: BLSSignature, withdrawal_credentials: Hash32, epoch_length: int) -> None: deposit_input = DepositInput( pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, proof_of_possession=EMPTY_SIGNATURE, ) is_valid_signature = bls.verify( pubkey=pubkey, # TODO: change to hash_tree_root(deposit_input) when we have SSZ tree hashing message=deposit_input.root, signature=proof_of_possession, domain=get_domain( state.fork, state.current_epoch(epoch_length), SignatureDomain.DOMAIN_DEPOSIT, ), ) if not is_valid_signature: raise ValidationError("BLS signature verification error")
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 sample_deposit_data_params(sample_deposit_input_params): return { 'deposit_input': DepositInput(**sample_deposit_input_params), 'amount': 56, 'timestamp': 1501851927, }
def test_get_genesis_beacon_state( privkeys, pubkeys, num_validators, genesis_epoch, genesis_slot, genesis_fork_version, genesis_start_shard, shard_count, min_seed_lookahead, latest_block_roots_length, latest_active_index_roots_length, slots_per_epoch, max_deposit_amount, latest_slashed_exit_length, latest_randao_mixes_length, activation_exit_delay, sample_eth1_data_params): withdrawal_credentials = b'\x22' * 32 fork = Fork( previous_version=genesis_fork_version, current_version=genesis_fork_version, epoch=genesis_epoch, ) validator_count = 5 genesis_validator_deposits = tuple( Deposit( branch=(b'\x11' * 32 for j in range(10)), index=i, deposit_data=DepositData( deposit_input=DepositInput( pubkey=pubkeys[i], withdrawal_credentials=withdrawal_credentials, proof_of_possession=sign_proof_of_possession( deposit_input=DepositInput( pubkey=pubkeys[i], withdrawal_credentials=withdrawal_credentials, ), privkey=privkeys[i], fork=fork, slot=genesis_slot, slots_per_epoch=slots_per_epoch, ), ), amount=max_deposit_amount, timestamp=0, ), ) for i in range(validator_count)) genesis_time = 10 latest_eth1_data = Eth1Data(**sample_eth1_data_params) state = get_genesis_beacon_state( genesis_validator_deposits=genesis_validator_deposits, genesis_time=genesis_time, latest_eth1_data=latest_eth1_data, genesis_epoch=genesis_epoch, genesis_slot=genesis_slot, genesis_fork_version=genesis_fork_version, genesis_start_shard=genesis_start_shard, shard_count=shard_count, min_seed_lookahead=min_seed_lookahead, latest_block_roots_length=latest_block_roots_length, latest_active_index_roots_length=latest_active_index_roots_length, slots_per_epoch=slots_per_epoch, max_deposit_amount=max_deposit_amount, latest_slashed_exit_length=latest_slashed_exit_length, latest_randao_mixes_length=latest_randao_mixes_length, activation_exit_delay=activation_exit_delay, ) # Misc assert state.slot == genesis_slot assert state.genesis_time == genesis_time assert state.fork.previous_version == genesis_fork_version assert state.fork.current_version == genesis_fork_version assert state.fork.epoch == genesis_epoch # Validator registry assert len(state.validator_registry) == validator_count assert len(state.validator_balances) == validator_count assert state.validator_registry_update_epoch == genesis_epoch # Randomness and committees assert len(state.latest_randao_mixes) == latest_randao_mixes_length assert state.previous_shuffling_start_shard == genesis_start_shard assert state.current_shuffling_start_shard == genesis_start_shard assert state.previous_shuffling_epoch == genesis_epoch assert state.current_shuffling_epoch == genesis_epoch assert state.previous_shuffling_seed == ZERO_HASH32 # Finality assert state.previous_justified_epoch == genesis_epoch assert state.justified_epoch == genesis_epoch assert state.justification_bitfield == 0 assert state.finalized_epoch == genesis_epoch # Recent state assert len(state.latest_crosslinks) == shard_count assert state.latest_crosslinks[0] == CrosslinkRecord( epoch=genesis_epoch, crosslink_data_root=ZERO_HASH32, ) assert len(state.latest_block_roots) == latest_block_roots_length assert state.latest_block_roots[0] == ZERO_HASH32 assert len(state.latest_slashed_balances) == latest_slashed_exit_length assert state.latest_slashed_balances[0] == Gwei(0) assert len(state.latest_attestations) == 0 assert len(state.batched_block_roots) == 0 # Ethereum 1.0 chain data assert state.latest_eth1_data == latest_eth1_data assert len(state.eth1_data_votes) == 0 assert state.deposit_index == len(genesis_validator_deposits) assert state.validator_registry[0].is_active(genesis_epoch)
def test_get_initial_beacon_state( privkeys, pubkeys, num_validators, genesis_epoch, genesis_slot, genesis_fork_version, genesis_start_shard, shard_count, seed_lookahead, latest_block_roots_length, latest_index_roots_length, epoch_length, max_deposit_amount, latest_penalized_exit_length, latest_randao_mixes_length, entry_exit_delay, sample_eth1_data_params): withdrawal_credentials = b'\x22' * 32 randao_commitment = b'\x33' * 32 custody_commitment = b'\x44' * 32 fork = Fork( previous_version=genesis_fork_version, current_version=genesis_fork_version, epoch=genesis_epoch, ) validator_count = 5 initial_validator_deposits = (Deposit( branch=(b'\x11' * 32 for j in range(10)), index=i, deposit_data=DepositData( deposit_input=DepositInput( pubkey=pubkeys[i], withdrawal_credentials=withdrawal_credentials, randao_commitment=randao_commitment, custody_commitment=custody_commitment, proof_of_possession=sign_proof_of_possession( deposit_input=DepositInput( pubkey=pubkeys[i], withdrawal_credentials=withdrawal_credentials, randao_commitment=randao_commitment, custody_commitment=custody_commitment, ), privkey=privkeys[i], fork=fork, slot=genesis_slot, epoch_length=epoch_length, ), ), amount=max_deposit_amount, timestamp=0, ), ) for i in range(validator_count)) genesis_time = 10 latest_eth1_data = Eth1Data(**sample_eth1_data_params) state = get_initial_beacon_state( initial_validator_deposits=initial_validator_deposits, genesis_time=genesis_time, latest_eth1_data=latest_eth1_data, genesis_epoch=genesis_epoch, genesis_slot=genesis_slot, genesis_fork_version=genesis_fork_version, genesis_start_shard=genesis_start_shard, shard_count=shard_count, seed_lookahead=seed_lookahead, latest_block_roots_length=latest_block_roots_length, latest_index_roots_length=latest_index_roots_length, epoch_length=epoch_length, max_deposit_amount=max_deposit_amount, latest_penalized_exit_length=latest_penalized_exit_length, latest_randao_mixes_length=latest_randao_mixes_length, entry_exit_delay=entry_exit_delay, ) # Misc assert state.slot == genesis_slot assert state.genesis_time == genesis_time assert state.fork.previous_version == genesis_fork_version assert state.fork.current_version == genesis_fork_version assert state.fork.epoch == genesis_epoch # Validator registry assert len(state.validator_registry) == validator_count assert len(state.validator_balances) == validator_count assert state.validator_registry_update_epoch == genesis_epoch assert state.validator_registry_exit_count == 0 # Randomness and committees assert len(state.latest_randao_mixes) == latest_randao_mixes_length assert len( state.latest_vdf_outputs) == latest_randao_mixes_length // epoch_length # TODO: `persistent_committees`, `persistent_committee_reassignments` will be removed assert len(state.persistent_committees) == 0 assert len(state.persistent_committee_reassignments) == 0 assert state.previous_epoch_start_shard == genesis_start_shard assert state.current_epoch_start_shard == genesis_start_shard assert state.previous_calculation_epoch == genesis_epoch assert state.current_calculation_epoch == genesis_epoch assert state.previous_epoch_seed == ZERO_HASH32 # Custody challenges assert len(state.custody_challenges) == 0 # Finality assert state.previous_justified_epoch == genesis_epoch assert state.justified_epoch == genesis_epoch assert state.justification_bitfield == 0 assert state.finalized_epoch == genesis_epoch # Recent state assert len(state.latest_crosslinks) == shard_count assert state.latest_crosslinks[0] == CrosslinkRecord( epoch=genesis_epoch, shard_block_root=ZERO_HASH32, ) assert len(state.latest_block_roots) == latest_block_roots_length assert state.latest_block_roots[0] == ZERO_HASH32 assert len(state.latest_penalized_balances) == latest_penalized_exit_length assert state.latest_penalized_balances[0] == Gwei(0) assert len(state.latest_attestations) == 0 assert len(state.batched_block_roots) == 0 # Ethereum 1.0 chain data assert state.latest_eth1_data == latest_eth1_data assert len(state.eth1_data_votes) == 0 assert state.validator_registry[0].is_active(genesis_epoch)
def test_defaults(sample_deposit_input_params): deposit_input = DepositInput(**sample_deposit_input_params) assert deposit_input.pubkey == sample_deposit_input_params['pubkey']