def test_deposit_in_block(spec, state): initial_registry_len = len(state.validators) initial_balances_len = len(state.balances) validator_index = len(state.validators) amount = spec.MAX_EFFECTIVE_BALANCE deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True) yield 'pre', state block = build_empty_block_for_next_slot(spec, state) block.body.deposits.append(deposit) signed_block = state_transition_and_sign_block(spec, state, block) yield 'blocks', [signed_block] yield 'post', state assert len(state.validators) == initial_registry_len + 1 assert len(state.balances) == initial_balances_len + 1 assert get_balance(state, validator_index) == spec.MAX_EFFECTIVE_BALANCE assert state.validators[validator_index].pubkey == pubkeys[validator_index]
def test_check_if_validator_active(spec, state): active_validator_index = len(state.validators) - 1 assert spec.check_if_validator_active(state, active_validator_index) new_validator_index = len(state.validators) amount = spec.MAX_EFFECTIVE_BALANCE deposit = prepare_state_and_deposit(spec, state, new_validator_index, amount, signed=True) spec.process_deposit(state, deposit) assert not spec.check_if_validator_active(state, new_validator_index)
def test_success_top_up(state): validator_index = 0 amount = spec.MAX_EFFECTIVE_BALANCE // 4 deposit = prepare_state_and_deposit(state, validator_index, amount, signed=True) yield from run_deposit_processing(state, deposit, validator_index)
def test_invalid_sig_new_deposit(state): # fresh deposit = next validator index = validator appended to registry validator_index = len(state.validator_registry) amount = spec.MAX_EFFECTIVE_BALANCE deposit = prepare_state_and_deposit(state, validator_index, amount) yield from run_deposit_processing(state, deposit, validator_index, valid=True, effective=False)
def test_invalid_sig_top_up(state): validator_index = 0 amount = spec.MAX_EFFECTIVE_BALANCE // 4 deposit = prepare_state_and_deposit(state, validator_index, amount) # invalid signatures, in top-ups, are allowed! yield from run_deposit_processing(state, deposit, validator_index, valid=True, effective=True)
def test_new_deposit_under_max(spec, state): # fresh deposit = next validator index = validator appended to registry validator_index = len(state.validators) # effective balance will be 1 EFFECTIVE_BALANCE_INCREMENT smaller because of this small decrement. amount = spec.MAX_EFFECTIVE_BALANCE - 1 deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True) yield from run_deposit_processing(spec, state, deposit, validator_index)
def test_new_deposit_over_max(spec, state): # fresh deposit = next validator index = validator appended to registry validator_index = len(state.validators) # just 1 over the limit, effective balance should be set MAX_EFFECTIVE_BALANCE during processing amount = spec.MAX_EFFECTIVE_BALANCE + 1 deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True) yield from run_deposit_processing(spec, state, deposit, validator_index)
def test_new_deposit_max(spec, state): # fresh deposit = next validator index = validator appended to registry validator_index = len(state.validators) # effective balance will be exactly the same as balance. amount = spec.MAX_EFFECTIVE_BALANCE deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True) yield from run_deposit_processing(spec, state, deposit, validator_index)
def test_bad_merkle_proof(state): validator_index = len(state.validator_registry) amount = spec.MAX_EFFECTIVE_BALANCE deposit = prepare_state_and_deposit(state, validator_index, amount) # mess up merkle branch deposit.proof[-1] = spec.ZERO_HASH sign_deposit_data(state, deposit.data, privkeys[validator_index]) yield from run_deposit_processing(state, deposit, validator_index, valid=False)
def test_wrong_index(state): validator_index = len(state.validator_registry) amount = spec.MAX_EFFECTIVE_BALANCE deposit = prepare_state_and_deposit(state, validator_index, amount) # mess up deposit_index deposit.index = state.deposit_index + 1 sign_deposit_data(state, deposit.data, privkeys[validator_index]) yield from run_deposit_processing(state, deposit, validator_index, valid=False)
def test_valid_sig_but_forked_state(spec, state): validator_index = len(state.validators) amount = spec.MAX_EFFECTIVE_BALANCE # deposits will always be valid, regardless of the current fork state.fork.current_version = spec.Version('0x1234abcd') deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True) yield from run_deposit_processing(spec, state, deposit, validator_index, valid=True, effective=True)
def test_bad_merkle_proof(spec, state): validator_index = len(state.validators) amount = spec.MAX_EFFECTIVE_BALANCE deposit = prepare_state_and_deposit(spec, state, validator_index, amount) # mess up merkle branch deposit.proof[5] = spec.Bytes32() sign_deposit_data(spec, deposit.data, privkeys[validator_index], state=state) yield from run_deposit_processing(spec, state, deposit, validator_index, valid=False)
def test_new_deposit_non_versioned_withdrawal_credentials(spec, state): # fresh deposit = next validator index = validator appended to registry validator_index = len(state.validators) withdrawal_credentials = ( b'\xFF' # Non specified withdrawal credentials version + b'\x02' * 31 # Garabage bytes ) amount = spec.MAX_EFFECTIVE_BALANCE deposit = prepare_state_and_deposit( spec, state, validator_index, amount, withdrawal_credentials=withdrawal_credentials, signed=True, ) yield from run_deposit_processing(spec, state, deposit, validator_index)
def test_invalid_withdrawal_credentials_top_up(state): validator_index = 0 amount = spec.MAX_EFFECTIVE_BALANCE // 4 withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX_BYTE + spec.hash( b"junk")[1:] deposit = prepare_state_and_deposit( state, validator_index, amount, withdrawal_credentials=withdrawal_credentials, ) # inconsistent withdrawal credentials, in top-ups, are allowed! yield from run_deposit_processing(state, deposit, validator_index, valid=True, effective=True)
def test_new_deposit_eth1_withdrawal_credentials(spec, state): # fresh deposit = next validator index = validator appended to registry validator_index = len(state.validators) withdrawal_credentials = ( spec.ETH1_ADDRESS_WITHDRAWAL_PREFIX + b'\x00' * 11 # specified 0s + b'\x59' * 20 # a 20-byte eth1 address ) amount = spec.MAX_EFFECTIVE_BALANCE deposit = prepare_state_and_deposit( spec, state, validator_index, amount, withdrawal_credentials=withdrawal_credentials, signed=True, ) yield from run_deposit_processing(spec, state, deposit, validator_index)
def test_deposit_top_up(spec, state): validator_index = 0 amount = spec.MAX_EFFECTIVE_BALANCE // 4 deposit = prepare_state_and_deposit(spec, state, validator_index, amount) initial_registry_len = len(state.validators) initial_balances_len = len(state.balances) validator_pre_balance = get_balance(state, validator_index) pre_state = state.copy() yield 'pre', pre_state block = build_empty_block_for_next_slot(spec, state) block.body.deposits.append(deposit) signed_block = state_transition_and_sign_block(spec, state, block) yield 'blocks', [signed_block] yield 'post', state assert len(state.validators) == initial_registry_len assert len(state.balances) == initial_balances_len # Altair introduces sync committee (sm) reward and penalty sync_committee_reward = sync_committee_penalty = 0 if is_post_altair(spec): committee_indices = compute_committee_indices( spec, state, state.current_sync_committee) committee_bits = block.body.sync_aggregate.sync_committee_bits sync_committee_reward, sync_committee_penalty = compute_sync_committee_participant_reward_and_penalty( spec, pre_state, validator_index, committee_indices, committee_bits, ) assert get_balance(state, validator_index) == (validator_pre_balance + amount + sync_committee_reward - sync_committee_penalty)
def test_deposit_top_up(spec, state): validator_index = 0 amount = spec.MAX_EFFECTIVE_BALANCE // 4 deposit = prepare_state_and_deposit(spec, state, validator_index, amount) initial_registry_len = len(state.validators) initial_balances_len = len(state.balances) validator_pre_balance = get_balance(state, validator_index) yield 'pre', state block = build_empty_block_for_next_slot(spec, state) block.body.deposits.append(deposit) signed_block = state_transition_and_sign_block(spec, state, block) yield 'blocks', [signed_block] yield 'post', state assert len(state.validators) == initial_registry_len assert len(state.balances) == initial_balances_len assert get_balance(state, validator_index) == validator_pre_balance + amount
def run_transition_with_operation(state, fork_epoch, spec, post_spec, pre_tag, post_tag, operation_type, operation_at_slot): """ Generate `operation_type` operation with the spec before fork. The operation would be included into the block at `operation_at_slot`. """ is_at_fork = operation_at_slot == fork_epoch * spec.SLOTS_PER_EPOCH is_right_before_fork = operation_at_slot == fork_epoch * spec.SLOTS_PER_EPOCH - 1 assert is_at_fork or is_right_before_fork if is_at_fork: transition_until_fork(spec, state, fork_epoch) elif is_right_before_fork: _transition_until_fork_minus_one(spec, state, fork_epoch) is_slashing_operation = operation_type in (OperationType.PROPOSER_SLASHING, OperationType.ATTESTER_SLASHING) # prepare operation selected_validator_index = None if is_slashing_operation: # avoid slashing the next proposer future_state = state.copy() next_slot(spec, future_state) proposer_index = spec.get_beacon_proposer_index(future_state) selected_validator_index = (proposer_index + 1) % len(state.validators) if operation_type == OperationType.PROPOSER_SLASHING: proposer_slashing = get_valid_proposer_slashing( spec, state, slashed_index=selected_validator_index, signed_1=True, signed_2=True) operation_dict = {'proposer_slashings': [proposer_slashing]} else: # operation_type == OperationType.ATTESTER_SLASHING: attester_slashing = get_valid_attester_slashing_by_indices( spec, state, [selected_validator_index], signed_1=True, signed_2=True, ) operation_dict = {'attester_slashings': [attester_slashing]} elif operation_type == OperationType.DEPOSIT: # create a new deposit selected_validator_index = len(state.validators) amount = spec.MAX_EFFECTIVE_BALANCE deposit = prepare_state_and_deposit(spec, state, selected_validator_index, amount, signed=True) operation_dict = {'deposits': [deposit]} elif operation_type == OperationType.VOLUNTARY_EXIT: selected_validator_index = 0 signed_exits = prepare_signed_exits(spec, state, [selected_validator_index]) operation_dict = {'voluntary_exits': signed_exits} def _check_state(): if operation_type == OperationType.PROPOSER_SLASHING: slashed_proposer = state.validators[ proposer_slashing.signed_header_1.message.proposer_index] assert slashed_proposer.slashed elif operation_type == OperationType.ATTESTER_SLASHING: indices = set( attester_slashing.attestation_1.attesting_indices ).intersection(attester_slashing.attestation_2.attesting_indices) assert selected_validator_index in indices assert len(indices) > 0 for validator_index in indices: assert state.validators[validator_index].slashed elif operation_type == OperationType.DEPOSIT: assert not post_spec.is_active_validator( state.validators[selected_validator_index], post_spec.get_current_epoch(state)) elif operation_type == OperationType.VOLUNTARY_EXIT: validator = state.validators[selected_validator_index] assert validator.exit_epoch < post_spec.FAR_FUTURE_EPOCH yield "pre", state blocks = [] if is_right_before_fork: # add a block with operation. block = build_empty_block_for_next_slot(spec, state) _set_operations_by_dict(block, operation_dict) signed_block = state_transition_and_sign_block(spec, state, block) blocks.append(pre_tag(signed_block)) _check_state() # irregular state transition to handle fork: _operation_at_slot = operation_dict if is_at_fork else None state, block = do_fork(state, spec, post_spec, fork_epoch, operation_dict=_operation_at_slot) blocks.append(post_tag(block)) if is_at_fork: _check_state() # after the fork if operation_type == OperationType.DEPOSIT: state = _transition_until_active(post_spec, state, post_tag, blocks, selected_validator_index) else: # avoid using the slashed validators as block proposers ignoring_proposers = [selected_validator_index ] if is_slashing_operation else None # continue regular state transition with new spec into next epoch transition_to_next_epoch_and_append_blocks( post_spec, state, post_tag, blocks, only_last_block=True, ignoring_proposers=ignoring_proposers, ) yield "blocks", blocks yield "post", state