def test_success_max_per_slot_in_queue(spec, state): prepare_withdrawals_queue(spec, state, spec.MAX_WITHDRAWALS_PER_PAYLOAD) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) yield from run_withdrawals_processing(spec, state, execution_payload)
def test_pending_shard_parent_block(spec, state): # Block N beacon_state = state.copy() transition_to_valid_shard_slot(spec, beacon_state) shard = 0 shard_state = beacon_state.shard_states[shard] signed_shard_block_1 = build_shard_block(spec, beacon_state, shard, slot=beacon_state.slot, signed=True) _, _, _, _ = run_shard_blocks(spec, shard_state, signed_shard_block_1, beacon_state) # Block N+1 next_slot(spec, beacon_state) signed_shard_block_2 = build_shard_block(spec, beacon_state, shard, slot=beacon_state.slot, shard_parent_state=shard_state, signed=True) assert signed_shard_block_2.message.shard_parent_root == shard_state.latest_block_root assert signed_shard_block_2.message.slot == signed_shard_block_1.message.slot + 1 yield from run_shard_blocks(spec, shard_state, signed_shard_block_2, beacon_state)
def test_success_empty_queue(spec, state): assert len(state.withdrawals_queue) == 0 next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) yield from run_withdrawals_processing(spec, state, execution_payload)
def test_success_one_in_queue(spec, state): prepare_withdrawals_queue(spec, state, 1) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) yield from run_withdrawals_processing(spec, state, execution_payload)
def test_on_attestation_inconsistent_target_and_head(spec, state): store = get_genesis_forkchoice_store(spec, state) spec.on_tick(store, store.time + 2 * spec.config.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH) # Create chain 1 as empty chain between genesis and start of 1st epoch target_state_1 = state.copy() next_epoch(spec, target_state_1) # Create chain 2 with different block in chain from chain 1 from chain 1 from chain 1 from chain 1 target_state_2 = state.copy() diff_block = build_empty_block_for_next_slot(spec, target_state_2) signed_diff_block = state_transition_and_sign_block(spec, target_state_2, diff_block) spec.on_block(store, signed_diff_block) next_epoch(spec, target_state_2) next_slot(spec, target_state_2) # Create and store block new head block on target state 1 head_block = build_empty_block_for_next_slot(spec, target_state_1) signed_head_block = state_transition_and_sign_block(spec, target_state_1, head_block) spec.on_block(store, signed_head_block) # Attest to head of chain 1 attestation = get_valid_attestation(spec, target_state_1, slot=head_block.slot, signed=False) epoch = spec.compute_epoch_at_slot(attestation.data.slot) # Set attestation target to be from chain 2 attestation.data.target = spec.Checkpoint(epoch=epoch, root=spec.get_block_root(target_state_2, epoch)) sign_attestation(spec, state, attestation) assert attestation.data.target.epoch == spec.GENESIS_EPOCH + 1 assert spec.compute_epoch_at_slot(attestation.data.slot) == spec.GENESIS_EPOCH + 1 assert spec.get_block_root(target_state_1, epoch) != attestation.data.target.root run_on_attestation(spec, state, store, attestation, False)
def run_generated_randomized_test(spec, state, scenario): stats = _compute_statistics(scenario) if "setup" not in scenario: state_randomizer = _resolve_ref(scenario.get("state_randomizer", randomize_state)) scenario["setup"] = _randomized_scenario_setup(state_randomizer) scenario_state = {} for mutation, validation in scenario["setup"]: additional_state = mutation(spec, state, stats) validation(spec, state) if additional_state: scenario_state.update(additional_state) yield "pre", state blocks = [] for transition in scenario["transitions"]: epochs_to_skip = _iter_temporal(spec, transition["epochs_to_skip"]) for _ in epochs_to_skip: next_epoch(spec, state) slots_to_skip = _iter_temporal(spec, transition["slots_to_skip"]) for _ in slots_to_skip: next_slot(spec, state) block_producer = _resolve_ref(transition["block_producer"]) block = block_producer(spec, state, blocks, scenario_state) if block: signed_block = state_transition_and_sign_block(spec, state, block) blocks.append(signed_block) validation = _resolve_ref(transition["validation"]) assert validation(spec, state) yield "blocks", blocks yield "post", state
def test_attestations_some_slashed(spec, state): attestations = [] for slot in range(spec.SLOTS_PER_EPOCH + spec.MIN_ATTESTATION_INCLUSION_DELAY): # create an attestation for each slot in epoch if slot < spec.SLOTS_PER_EPOCH: attestation = get_valid_attestation(spec, state, signed=True) attestations.append(attestation) # fill each created slot in state after inclusion delay if slot - spec.MIN_ATTESTATION_INCLUSION_DELAY >= 0: include_att = attestations[slot - spec.MIN_ATTESTATION_INCLUSION_DELAY] add_attestations_to_state(spec, state, [include_att], state.slot) next_slot(spec, state) attesting_indices_before_slashings = list(spec.get_unslashed_attesting_indices(state, attestations)) # Slash maximum amount of validators allowed per epoch. for i in range(spec.MIN_PER_EPOCH_CHURN_LIMIT): spec.slash_validator(state, attesting_indices_before_slashings[i]) assert spec.compute_epoch_at_slot(state.slot) == spec.GENESIS_EPOCH + 1 assert len(state.previous_epoch_attestations) == spec.SLOTS_PER_EPOCH pre_state = deepcopy(state) yield from run_process_rewards_and_penalties(spec, state) attesting_indices = spec.get_unslashed_attesting_indices(state, attestations) assert len(attesting_indices) > 0 assert len(attesting_indices_before_slashings) - len(attesting_indices) == spec.MIN_PER_EPOCH_CHURN_LIMIT for index in range(len(pre_state.validators)): if index in attesting_indices: assert state.balances[index] > pre_state.balances[index] else: assert state.balances[index] < pre_state.balances[index]
def prepare_state_with_full_attestations(spec, state, empty=False): # Go to start of next epoch to ensure can have full participation next_epoch(spec, state) start_slot = state.slot start_epoch = spec.get_current_epoch(state) next_epoch_start_slot = spec.compute_start_slot_at_epoch(start_epoch + 1) attestations = [] for _ in range(spec.SLOTS_PER_EPOCH + spec.MIN_ATTESTATION_INCLUSION_DELAY): # create an attestation for each index in each slot in epoch if state.slot < next_epoch_start_slot: for committee_index in range( spec.get_committee_count_at_slot(state, state.slot)): attestation = get_valid_attestation(spec, state, index=committee_index, empty=empty, signed=True) attestations.append(attestation) # fill each created slot in state after inclusion delay if state.slot >= start_slot + spec.MIN_ATTESTATION_INCLUSION_DELAY: inclusion_slot = state.slot - spec.MIN_ATTESTATION_INCLUSION_DELAY include_attestations = [ att for att in attestations if att.data.slot == inclusion_slot ] add_attestations_to_state(spec, state, include_attestations, state.slot) next_slot(spec, state) assert state.slot == next_epoch_start_slot + spec.MIN_ATTESTATION_INCLUSION_DELAY assert len(state.previous_epoch_attestations) == len(attestations) return attestations
def test_empty_aggregation_bits(spec, state): next_slot(spec, state) attestation = get_valid_attestation(spec, state, empty=True) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) assert attestation.aggregation_bits == Bitlist[spec.MAX_VALIDATORS_PER_COMMITTEE]( *([0b0] * len(attestation.aggregation_bits))) yield from run_attestation_processing(spec, state, attestation)
def test_success_regular_payload(spec, state): # pre-state state = build_state_with_complete_transition(spec, state) next_slot(spec, state) # execution payload execution_payload = build_empty_execution_payload(spec, state) yield from run_execution_payload_processing(spec, state, execution_payload)
def test_no_winning_root(spec, state): if not is_full_crosslink(spec, state): # Skip this test return state, shard, target_shard_slot = get_initial_env(spec, state, target_len_offset_slot=1) init_slot = state.slot # Create SignedShardBlock at init_slot shard_block = build_shard_block(spec, state, shard, slot=init_slot, body=get_sample_shard_block_body( spec, is_max=True), signed=True) # Transition state to target shard slot transition_to(spec, state, target_shard_slot) # Create a shard_transitions that would be included at beacon block `target_shard_slot + 1` shard_transitions = get_shard_transitions(spec, state, {shard: [shard_block]}) shard_transition = shard_transitions[shard] committee_index = get_committee_index_of_shard(spec, state, state.slot, shard) attestation = get_valid_attestation( spec, state, index=committee_index, shard_transition=shard_transition, # Decrease attested participants to 1/3 committee filter_participant_set=lambda committee: set( list(committee)[:len(committee) // 3]), signed=True, on_time=True, ) next_slot(spec, state) _, _, _ = run_attestation_processing(spec, state, attestation) _, winning_roots = spec.get_shard_winning_roots(state, [attestation]) assert len(winning_roots) == 0 # No winning root, shard_transitions[shard] is empty shard_transitions = [spec.ShardTransition()] * spec.MAX_SHARDS pre_shard_states = state.shard_states.copy() yield from run_shard_transitions_processing(spec, state, shard_transitions, [attestation]) for pending_attestation in state.current_epoch_attestations: assert bool(pending_attestation.crosslink_success) is False assert state.shard_states == pre_shard_states
def test_wrong_shard_transition_root(spec, state): if not is_full_crosslink(spec, state): # Skip this test return state, shard, target_shard_slot = get_initial_env(spec, state, target_len_offset_slot=1) init_slot = state.slot # Create SignedShardBlock at init_slot shard_block = build_shard_block(spec, state, shard, slot=init_slot, body=get_sample_shard_block_body( spec, is_max=True), signed=True) # Transition state to target shard slot transition_to(spec, state, target_shard_slot) # Create a shard_transitions that would be included at beacon block `target_shard_slot + 1` shard_transitions = get_shard_transitions(spec, state, {shard: [shard_block]}) shard_transition = shard_transitions[shard] wrong_shard_transition = shard_transition.copy() wrong_shard_transition.shard_states[ shard].gasprice = shard_transition.shard_states[shard].gasprice + 1 committee_index = get_committee_index_of_shard(spec, state, state.slot, shard) attestation = get_valid_attestation( spec, state, index=committee_index, shard_transition=wrong_shard_transition, signed=True, on_time=True, ) attestations = [attestation] next_slot(spec, state) run_attestation_processing(spec, state, attestation) # Check if winning root != shard_transition.hash_tree_root() _, winning_roots = spec.get_shard_winning_roots(state, attestations) assert len(winning_roots) == 1 shard_transition = shard_transitions[shard] assert winning_roots[0] != shard_transition.hash_tree_root() yield from run_shard_transitions_processing(spec, state, shard_transitions, attestations, valid=False)
def test_bad_random_regular_payload(spec, state): # pre-state state = build_state_with_complete_transition(spec, state) next_slot(spec, state) # execution payload execution_payload = build_empty_execution_payload(spec, state) execution_payload.random = b'\x04' * 32 yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
def test_gaslimit_max_first_payload(spec, state): # pre-state state = build_state_with_incomplete_transition(spec, state) next_slot(spec, state) # execution payload execution_payload = build_empty_execution_payload(spec, state) execution_payload.gas_limit = uint64(2**64 - 1) yield from run_execution_payload_processing(spec, state, execution_payload)
def test_bad_parent_hash_regular_payload(spec, state): # pre-state state = build_state_with_complete_transition(spec, state) next_slot(spec, state) # execution payload execution_payload = build_empty_execution_payload(spec, state) execution_payload.parent_hash = spec.Hash32() yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
def test_bad_timestamp_regular_payload(spec, state): # pre-state state = build_state_with_complete_transition(spec, state) next_slot(spec, state) # execution payload execution_payload = build_empty_execution_payload(spec, state) execution_payload.timestamp = execution_payload.timestamp + 1 yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
def test_gasused_gaslimit_plus_regular_payload(spec, state): # pre-state state = build_state_with_complete_transition(spec, state) next_slot(spec, state) # execution payload execution_payload = build_empty_execution_payload(spec, state) execution_payload.gas_used = execution_payload.gas_limit + uint64(1) yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
def test_bad_execution_regular_payload(spec, state): # completely valid payload, but execution itself fails (e.g. block exceeds gas limit) # pre-state state = build_state_with_complete_transition(spec, state) next_slot(spec, state) # execution payload execution_payload = build_empty_execution_payload(spec, state) yield from run_execution_payload_processing(spec, state, execution_payload, valid=False, execution_valid=False)
def test_fail_incorrect_dequeue_amount(spec, state): prepare_withdrawals_queue(spec, state, 1) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) execution_payload.withdrawals[0].amount += 1 yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
def test_fail_max_per_slot_in_queue_one_less_in_withdrawals(spec, state): prepare_withdrawals_queue(spec, state, spec.MAX_WITHDRAWALS_PER_PAYLOAD) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) execution_payload.withdrawals = execution_payload.withdrawals[:-1] yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
def test_gaslimit_minimum_minus_regular_payload(spec, state): # pre-state state = build_state_with_complete_transition(spec, state) next_slot(spec, state) state.latest_execution_payload_header.gas_limit = spec.MIN_GAS_LIMIT # execution payload execution_payload = build_empty_execution_payload(spec, state) execution_payload.gas_limit = execution_payload.gas_limit - uint64(1) yield from run_execution_payload_processing(spec, state, execution_payload, valid=False)
def test_fail_one_in_queue_none_in_withdrawals(spec, state): prepare_withdrawals_queue(spec, state, 1) next_slot(spec, state) execution_payload = build_empty_execution_payload(spec, state) execution_payload.withdrawals = [] yield from run_withdrawals_processing(spec, state, execution_payload, valid=False)
def test_on_attestation_same_slot(spec, state): store = spec.get_genesis_store(state) time = 1 * spec.SECONDS_PER_SLOT spec.on_tick(store, time) block = build_empty_block_for_next_slot(spec, state, signed=True) spec.on_block(store, block) next_slot(spec, state) attestation = get_valid_attestation(spec, state, slot=block.slot) run_on_attestation(spec, state, store, attestation, False)
def test_proposer_slashed(spec, state): # use stub state to get proposer index of next slot stub_state = deepcopy(state) next_slot(spec, stub_state) proposer_index = spec.get_beacon_proposer_index(stub_state) # set proposer to slashed state.validators[proposer_index].slashed = True block = build_empty_block_for_next_slot(spec, state) yield from run_block_header_processing(spec, state, block, valid=False)
def prepare_state_with_attestations(spec, state, participation_fn=None): """ Prepare state with attestations according to the ``participation_fn``. If no ``participation_fn``, default to "full" -- max committee participation at each slot. participation_fn: (slot, committee_index, committee_indices_set) -> participants_indices_set """ # Go to start of next epoch to ensure can have full participation next_epoch(spec, state) start_slot = state.slot start_epoch = spec.get_current_epoch(state) next_epoch_start_slot = spec.compute_start_slot_at_epoch(start_epoch + 1) attestations = [] for _ in range(spec.SLOTS_PER_EPOCH + spec.MIN_ATTESTATION_INCLUSION_DELAY): # create an attestation for each index in each slot in epoch if state.slot < next_epoch_start_slot: for committee_index in range( spec.get_committee_count_per_slot( state, spec.get_current_epoch(state))): def temp_participants_filter(comm): if participation_fn is None: return comm else: return participation_fn(state.slot, committee_index, comm) attestation = get_valid_attestation( spec, state, index=committee_index, filter_participant_set=temp_participants_filter, signed=True) if any(attestation.aggregation_bits ): # Only if there is at least 1 participant. attestations.append(attestation) # fill each created slot in state after inclusion delay if state.slot >= start_slot + spec.MIN_ATTESTATION_INCLUSION_DELAY: inclusion_slot = state.slot - spec.MIN_ATTESTATION_INCLUSION_DELAY include_attestations = [ att for att in attestations if att.data.slot == inclusion_slot ] add_attestations_to_state(spec, state, include_attestations, state.slot) next_slot(spec, state) assert state.slot == next_epoch_start_slot + spec.MIN_ATTESTATION_INCLUSION_DELAY if not is_post_altair(spec): assert len(state.previous_epoch_attestations) == len(attestations) return attestations
def test_non_empty_extra_data_regular_payload(spec, state): # pre-state state = build_state_with_complete_transition(spec, state) next_slot(spec, state) # execution payload execution_payload = build_empty_execution_payload(spec, state) execution_payload.extra_data = b'\x45' * 12 yield from run_execution_payload_processing(spec, state, execution_payload) assert state.latest_execution_payload_header.extra_data == execution_payload.extra_data
def test_bad_crosslink_end_epoch(spec, state): next_epoch(spec, state) apply_empty_block(spec, state) attestation = get_valid_attestation(spec, state, signed=True) for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY): next_slot(spec, state) apply_empty_block(spec, state) attestation.data.crosslink.end_epoch += 1 yield from run_attestation_processing(spec, state, attestation, False)
def test_bad_previous_crosslink(state): next_epoch(state) apply_empty_block(state) attestation = get_valid_attestation(state, signed=True) for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY): next_slot(state) apply_empty_block(state) state.current_crosslinks[attestation.data.shard].epoch += 10 yield from run_attestation_processing(state, attestation, False)
def test_gaslimit_lower_regular_payload(spec, state): # pre-state state = build_state_with_complete_transition(spec, state) next_slot(spec, state) # execution payload execution_payload = build_empty_execution_payload(spec, state) execution_payload.gas_limit = ( execution_payload.gas_limit - execution_payload.gas_limit // spec.GAS_LIMIT_DENOMINATOR + uint64(1) ) yield from run_execution_payload_processing(spec, state, execution_payload)
def _state_transition_across_slots(spec, state, to_slot, block_filter=_all_blocks): assert state.slot < to_slot while state.slot < to_slot: should_make_block = block_filter(state) if should_make_block: block = build_empty_block_for_next_slot(spec, state) signed_block = state_transition_and_sign_block(spec, state, block) yield signed_block else: next_slot(spec, state)