def test_randao_processing_validates_randao_reveal(sample_beacon_block_params, sample_beacon_state_params, sample_fork_params, keymap, config): proposer_pubkey, proposer_privkey = first(keymap.items()) state = SerenityBeaconState(**sample_beacon_state_params).copy( validator_registry=tuple( mock_validator_record(proposer_pubkey) for _ in range(config.TARGET_COMMITTEE_SIZE)), validator_balances=(config.MAX_DEPOSIT_AMOUNT, ) * config.TARGET_COMMITTEE_SIZE, latest_randao_mixes=tuple( ZERO_HASH32 for _ in range(config.LATEST_RANDAO_MIXES_LENGTH)), ) epoch = state.current_epoch(config.EPOCH_LENGTH) slot = epoch * config.EPOCH_LENGTH message = (epoch + 1).to_bytes(32, byteorder="big") fork = Fork(**sample_fork_params) domain = get_domain(fork, slot, SignatureDomain.DOMAIN_RANDAO) randao_reveal = bls.sign(message, proposer_privkey, domain) block = SerenityBeaconBlock(**sample_beacon_block_params).copy( randao_reveal=randao_reveal, ) with pytest.raises(ValidationError): process_randao(state, block, config)
def test_activate_validator(is_genesis, filled_beacon_state, genesis_epoch, epoch_length, entry_exit_delay, max_deposit_amount): validator_count = 10 state = filled_beacon_state.copy( validator_registry=tuple( mock_validator_record( pubkey=index.to_bytes(48, 'big'), is_active=False, ) for index in range(validator_count)), validator_balances=(max_deposit_amount, ) * validator_count, ) index = 1 # Check that the `index`th validator in `state` is inactivated assert state.validator_registry[index].activation_epoch == FAR_FUTURE_EPOCH result_state = activate_validator( state=state, index=index, is_genesis=is_genesis, genesis_epoch=genesis_epoch, epoch_length=epoch_length, entry_exit_delay=entry_exit_delay, ) if is_genesis: assert result_state.validator_registry[ index].activation_epoch == genesis_epoch else: assert (result_state.validator_registry[index].activation_epoch == get_entry_exit_effect_epoch( state.current_epoch(epoch_length), entry_exit_delay, ))
def test_randao_processing(sample_beacon_block_params, sample_beacon_state_params, sample_fork_params, keymap, config): proposer_pubkey, proposer_privkey = first(keymap.items()) state = SerenityBeaconState(**sample_beacon_state_params).copy( validator_registry=tuple( mock_validator_record(proposer_pubkey) for _ in range(config.TARGET_COMMITTEE_SIZE)), validator_balances=(config.MAX_DEPOSIT_AMOUNT, ) * config.TARGET_COMMITTEE_SIZE, latest_randao_mixes=tuple( ZERO_HASH32 for _ in range(config.LATEST_RANDAO_MIXES_LENGTH)), ) epoch = state.current_epoch(config.EPOCH_LENGTH) slot = epoch * config.EPOCH_LENGTH message = epoch.to_bytes(32, byteorder="big") fork = Fork(**sample_fork_params) domain = get_domain(fork, slot, SignatureDomain.DOMAIN_RANDAO) randao_reveal = bls.sign(message, proposer_privkey, domain) block = SerenityBeaconBlock(**sample_beacon_block_params).copy( randao_reveal=randao_reveal, ) new_state = process_randao(state, block, config) updated_index = epoch % config.LATEST_RANDAO_MIXES_LENGTH original_mixes = state.latest_randao_mixes updated_mixes = new_state.latest_randao_mixes assert all( updated == original if index != updated_index else updated != original for index, (updated, original) in enumerate(zip(updated_mixes, original_mixes)))
def test_num_validators(expected, max_deposit, filled_beacon_state): state = filled_beacon_state.copy( validator_registry=tuple( mock_validator_record(pubkey, ) for pubkey in range(expected)), validator_balances=(max_deposit * GWEI_PER_ETH, ) * expected, ) assert state.num_validators == expected
def test_validator_registry_and_balances_length(sample_beacon_state_params, config): # When len(BeaconState.validator_registry) != len(BeaconState.validtor_balances) with pytest.raises(ValueError): BeaconState(**sample_beacon_state_params).copy( validator_registry=tuple( mock_validator_record(pubkey, config) for pubkey in range(10)), )
def n_validators_state(filled_beacon_state, max_deposit_amount, n): validator_count = n return filled_beacon_state.copy( validator_registry=tuple( mock_validator_record( pubkey=index.to_bytes(48, "big"), is_active=True, ) for index in range(validator_count)), validator_balances=(max_deposit_amount, ) * validator_count, )
def ten_validators_state(empty_beacon_state, max_deposit): validator_count = 10 return empty_beacon_state.copy( validator_registry=tuple( mock_validator_record( pubkey=pubkey, is_active=True, ) for pubkey in range(validator_count) ), validator_balances=(max_deposit * GWEI_PER_ETH,) * validator_count, )
def genesis_validators(init_validator_pubkeys, init_randao, max_deposit_amount, config): """ Inactive """ return tuple( mock_validator_record( pubkey=pubkey, config=config, withdrawal_credentials=ZERO_HASH32, is_active=False, ) for pubkey in init_validator_pubkeys)
def initial_validators(init_validator_pubkeys, init_randao, max_deposit): """ Inactive """ return tuple( mock_validator_record( pubkey=pubkey, withdrawal_credentials=ZERO_HASH32, randao_commitment=init_randao, status_flags=0, is_active=False, ) for pubkey in init_validator_pubkeys)
def test_validate_serenity_proposer_signature( proposer_privkey, proposer_pubkey, is_valid_signature, sample_beacon_block_params, sample_beacon_state_params, sample_shard_committee_params, beacon_chain_shard_number, epoch_length, max_deposit): state = BeaconState(**sample_beacon_state_params).copy( validator_registry=tuple( mock_validator_record(proposer_pubkey) for _ in range(10)), validator_balances=(max_deposit * GWEI_PER_ETH, ) * 10, shard_committees_at_slots=get_sample_shard_committees_at_slots( num_slot=128, num_shard_committee_per_slot=10, sample_shard_committee_params=sample_shard_committee_params, ), ) default_block = BeaconBlock(**sample_beacon_block_params) empty_signature_block_root = default_block.block_without_signature_root proposal_root = ProposalSignedData( state.slot, beacon_chain_shard_number, empty_signature_block_root, ).root proposed_block = BeaconBlock(**sample_beacon_block_params).copy( signature=bls.sign( message=proposal_root, privkey=proposer_privkey, domain=SignatureDomain.DOMAIN_PROPOSAL, ), ) if is_valid_signature: validate_serenity_proposer_signature( state, proposed_block, beacon_chain_shard_number, epoch_length, ) else: with pytest.raises(ValidationError): validate_serenity_proposer_signature( state, proposed_block, beacon_chain_shard_number, epoch_length, )
def test_randao_processing(sample_beacon_block_params, sample_beacon_block_body_params, sample_beacon_state_params, keymap, config): proposer_pubkey, proposer_privkey = first(keymap.items()) state = SerenityBeaconState(**sample_beacon_state_params).copy( validator_registry=tuple( mock_validator_record(proposer_pubkey, config) for _ in range(config.TARGET_COMMITTEE_SIZE) ), validator_balances=(config.MAX_DEPOSIT_AMOUNT,) * config.TARGET_COMMITTEE_SIZE, latest_randao_mixes=tuple( ZERO_HASH32 for _ in range(config.LATEST_RANDAO_MIXES_LENGTH) ), ) epoch = state.current_epoch(config.SLOTS_PER_EPOCH) slot = get_epoch_start_slot(epoch, config.SLOTS_PER_EPOCH) randao_reveal = _generate_randao_reveal( privkey=proposer_privkey, slot=slot, fork=state.fork, config=config, ) block_body = BeaconBlockBody(**sample_beacon_block_body_params).copy( randao_reveal=randao_reveal, ) block = SerenityBeaconBlock(**sample_beacon_block_params).copy( body=block_body, ) new_state = process_randao(state, block, config) updated_index = epoch % config.LATEST_RANDAO_MIXES_LENGTH original_mixes = state.latest_randao_mixes updated_mixes = new_state.latest_randao_mixes assert all( updated == original if index != updated_index else updated != original for index, (updated, original) in enumerate(zip(updated_mixes, original_mixes)) )
def test_validate_proposer_signature( slots_per_epoch, shard_count, proposer_privkey, proposer_pubkey, is_valid_signature, sample_beacon_block_params, sample_beacon_state_params, beacon_chain_shard_number, genesis_epoch, target_committee_size, max_deposit_amount, config): state = BeaconState(**sample_beacon_state_params).copy( validator_registry=tuple( mock_validator_record(proposer_pubkey, config) for _ in range(10)), validator_balances=(max_deposit_amount, ) * 10, ) default_block = BeaconBlock(**sample_beacon_block_params) empty_signature_block_root = default_block.block_without_signature_root proposal_signed_root = Proposal( state.slot, beacon_chain_shard_number, empty_signature_block_root, ).signed_root proposed_block = BeaconBlock(**sample_beacon_block_params).copy( signature=bls.sign( message_hash=proposal_signed_root, privkey=proposer_privkey, domain=SignatureDomain.DOMAIN_PROPOSAL, ), ) if is_valid_signature: validate_proposer_signature( state, proposed_block, beacon_chain_shard_number, CommitteeConfig(config), ) else: with pytest.raises(ValidationError): validate_proposer_signature( state, proposed_block, beacon_chain_shard_number, CommitteeConfig(config), )
def test_update_validator(ten_validators_state, validator_index, new_pubkey, new_balance): state = ten_validators_state validator = mock_validator_record(new_pubkey) if validator_index < state.num_validators: result_state = state.update_validator( validator_index=validator_index, validator=validator, balance=new_balance, ) assert result_state.validator_balances[validator_index] == new_balance assert result_state.validator_registry[ validator_index].pubkey == new_pubkey assert state.validator_registry[validator_index].pubkey != new_pubkey else: with pytest.raises(IndexError): state.update_validator( validator_index=validator_index, validator=validator, balance=new_balance, )
def test_activate_validator(genesis, filled_beacon_state, genesis_slot, entry_exit_delay, max_deposit): validator_count = 10 state = filled_beacon_state.copy( validator_registry=tuple( mock_validator_record( pubkey=index.to_bytes(48, 'big'), is_active=False, ) for index in range(validator_count)), validator_balances=(max_deposit * GWEI_PER_ETH, ) * validator_count, ) index = 1 # Check that the `index`th validator in `state` is inactivated assert state.validator_registry[index].activation_slot == FAR_FUTURE_SLOT result_state = activate_validator( state=state, index=index, genesis=genesis, genesis_slot=genesis_slot, entry_exit_delay=entry_exit_delay, ) result_validator = result_state.validator_registry[index] new_validator_registry_delta_chain_tip = ValidatorRegistryDeltaBlock( latest_registry_delta_root=state.validator_registry_delta_chain_tip, validator_index=index, pubkey=result_validator.pubkey, slot=result_validator.activation_slot, flag=ValidatorRegistryDeltaFlag.ACTIVATION, ).root assert (result_state.validator_registry_delta_chain_tip == new_validator_registry_delta_chain_tip) if genesis: state.validator_registry[index].activation_slot == genesis_slot else: state.validator_registry[ index].activation_slot == state.slot + entry_exit_delay