def test_success_previous_epoch(spec, state): attestation = get_valid_attestation(spec, state, signed=True) state.slot = spec.SLOTS_PER_EPOCH - 1 next_epoch(spec, state) apply_empty_block(spec, state) yield from run_attestation_processing(spec, state, attestation)
def test_duplicate_attestation(spec, state): """ Although duplicate attestations can be included on-chain, they should only be rewarded for once. This test addresses this issue found at Interop https://github.com/djrtwo/interop-test-cases/tree/master/tests/prysm_16_duplicate_attestation_rewards """ attestation = get_valid_attestation(spec, state, signed=True) indexed_attestation = spec.get_indexed_attestation(state, attestation) participants = indexed_attestation.custody_bit_0_indices + indexed_attestation.custody_bit_1_indices assert len(participants) > 0 single_state = deepcopy(state) dup_state = deepcopy(state) inclusion_slot = state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY add_attestations_to_state(spec, single_state, [attestation], inclusion_slot) add_attestations_to_state(spec, dup_state, [attestation, attestation], inclusion_slot) next_epoch(spec, single_state) next_epoch(spec, dup_state) # Run non-duplicate inclusion rewards for comparision. Do not yield test vectors for _ in run_process_rewards_and_penalties(spec, single_state): pass # Output duplicate inclusion to test vectors yield from run_process_rewards_and_penalties(spec, dup_state) for index in participants: assert state.balances[index] < single_state.balances[index] assert single_state.balances[index] == dup_state.balances[index]
def test_empty_participants_zeroes_sig(spec, state): attestation = get_valid_attestation( spec, state, filter_participant_set=lambda comm: []) # 0 participants attestation.signature = spec.BLSSignature(b'\x00' * 96) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) yield from run_attestation_processing(spec, state, attestation, False)
def test_attestation(spec, state): state.slot = spec.SLOTS_PER_EPOCH yield 'pre', state attestation = get_valid_attestation(spec, state, signed=True) # Add to state via block transition pre_current_attestations_len = len(state.current_epoch_attestations) attestation_block = build_empty_block_for_next_slot(spec, state) attestation_block.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation_block.body.attestations.append(attestation) sign_block(spec, state, attestation_block) state_transition_and_sign_block(spec, state, attestation_block) assert len(state.current_epoch_attestations) == pre_current_attestations_len + 1 # Epoch transition should move to previous_epoch_attestations pre_current_attestations_root = spec.hash_tree_root(state.current_epoch_attestations) epoch_block = build_empty_block_for_next_slot(spec, state) epoch_block.slot += spec.SLOTS_PER_EPOCH sign_block(spec, state, epoch_block) state_transition_and_sign_block(spec, state, epoch_block) yield 'blocks', [attestation_block, epoch_block], List[spec.BeaconBlock] yield 'post', state assert len(state.current_epoch_attestations) == 0 assert spec.hash_tree_root(state.previous_epoch_attestations) == pre_current_attestations_root
def test_shorter_chain_but_heavier_weight(spec, state): genesis_state = state.copy() # Initialization store = spec.get_forkchoice_store(state) anchor_root = get_anchor_root(spec, state) assert spec.get_head(store) == anchor_root # build longer tree long_state = genesis_state.copy() for i in range(3): long_block = build_empty_block_for_next_slot(spec, long_state) signed_long_block = state_transition_and_sign_block(spec, long_state, long_block) add_block_to_store(spec, store, signed_long_block) # build short tree short_state = genesis_state.copy() short_block = build_empty_block_for_next_slot(spec, short_state) short_block.body.graffiti = b'\x42' * 32 signed_short_block = state_transition_and_sign_block(spec, short_state, short_block) add_block_to_store(spec, store, signed_short_block) short_attestation = get_valid_attestation(spec, short_state, short_block.slot, signed=True) add_attestation_to_store(spec, store, short_attestation) assert spec.get_head(store) == spec.hash_tree_root(short_block)
def test_invalid_current_source_root(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH * 5) state.finalized_checkpoint.epoch = 2 state.previous_justified_checkpoint = spec.Checkpoint(epoch=3, root=b'\x01' * 32) state.current_justified_checkpoint = spec.Checkpoint(epoch=4, root=b'\x32' * 32) attestation = get_valid_attestation(spec, state, slot=(spec.SLOTS_PER_EPOCH * 3) + 1, on_time=False) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) # Test logic sanity checks: assert state.current_justified_checkpoint.root != state.previous_justified_checkpoint.root assert attestation.data.source.root == state.previous_justified_checkpoint.root # Make attestation source root invalid: should be previous justified, not current one attestation.data.source.root = state.current_justified_checkpoint.root sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation, False)
def test_on_attestation_target_checkpoint_not_in_store_diff_slot(spec, state): store = get_genesis_forkchoice_store(spec, state) time = store.time + spec.SECONDS_PER_SLOT * (spec.SLOTS_PER_EPOCH + 1) spec.on_tick(store, time) # move to two slots before next epoch to make target block one before an empty slot next_epoch = spec.get_current_epoch(state) + 1 transition_to(spec, state, spec.compute_start_slot_at_epoch(next_epoch) - 2) target_block = build_empty_block_for_next_slot(spec, state) signed_target_block = state_transition_and_sign_block( spec, state, target_block) # add target block to store spec.on_block(store, signed_target_block) # target checkpoint state is not yet in store attestation_slot = target_block.slot + 1 transition_to(spec, state, attestation_slot) attestation = get_valid_attestation(spec, state, slot=attestation_slot, signed=True) assert attestation.data.target.root == target_block.hash_tree_root() run_on_attestation(spec, state, store, attestation)
def test_success_previous_epoch(spec, state): attestation = get_valid_attestation(spec, state, signed=True, on_time=False) transition_to(spec, state, spec.SLOTS_PER_EPOCH - 1) next_epoch(spec, state) apply_empty_block(spec, state) yield from run_attestation_processing(spec, state, attestation)
def test_late_success(spec, state): attestation = get_valid_attestation(spec, state, signed=True) transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY + 1) yield from run_attestation_processing(spec, state, attestation)
def test_single_crosslink_update_from_previous_epoch(spec, state): next_epoch(spec, state) attestation = get_valid_attestation(spec, state, signed=True) fill_aggregate_attestation(spec, state, attestation) add_attestation_to_state(spec, state, attestation, state.slot + spec.SLOTS_PER_EPOCH) assert len(state.previous_epoch_attestations) == 1 shard = attestation.data.crosslink.shard pre_crosslink = deepcopy(state.current_crosslinks[shard]) crosslink_deltas = spec.get_crosslink_deltas(state) yield from run_process_crosslinks(spec, state) assert state.previous_crosslinks[shard] != state.current_crosslinks[shard] assert pre_crosslink != state.current_crosslinks[shard] # ensure rewarded for index in spec.get_crosslink_committee( state, attestation.data.target_epoch, attestation.data.crosslink.shard): assert crosslink_deltas[0][index] > 0 assert crosslink_deltas[1][index] == 0
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 test_after_epoch_slots(state): attestation = get_valid_attestation(state, signed=True) # increment past latest inclusion slot state_transition_to(state, state.slot + spec.SLOTS_PER_EPOCH + 1) apply_empty_block(state) yield from run_attestation_processing(state, attestation, False)
def test_after_epoch_slots(spec, state): attestation = get_valid_attestation(spec, state, signed=True, on_time=False) # increment past latest inclusion slot transition_to_slot_via_block(spec, state, state.slot + spec.SLOTS_PER_EPOCH + 1) yield from run_attestation_processing(spec, state, attestation, False)
def test_empty_participants_seemingly_valid_sig(spec, state): attestation = get_valid_attestation(spec, state, filter_participant_set=lambda comm: []) # 0 participants # Special BLS value, valid for zero pubkeys on some (but not all) BLS implementations. attestation.signature = spec.BLSSignature(b'\xc0' + b'\x00' * 95) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) yield from run_attestation_processing(spec, state, attestation, False)
def test_on_attestation_beacon_block_not_in_store(spec, state): store = get_genesis_forkchoice_store(spec, state) time = store.time + spec.SECONDS_PER_SLOT * (spec.SLOTS_PER_EPOCH + 1) spec.on_tick(store, time) # move to immediately before next epoch to make block new target next_epoch = spec.get_current_epoch(state) + 1 transition_to(spec, state, spec.compute_start_slot_at_epoch(next_epoch) - 1) target_block = build_empty_block_for_next_slot(spec, state) signed_target_block = state_transition_and_sign_block( spec, state, target_block) # store target in store spec.on_block(store, signed_target_block) head_block = build_empty_block_for_next_slot(spec, state) state_transition_and_sign_block(spec, state, head_block) # do not add head block to store attestation = get_valid_attestation(spec, state, slot=head_block.slot, signed=True) assert attestation.data.target.root == target_block.hash_tree_root() assert attestation.data.beacon_block_root == head_block.hash_tree_root() run_on_attestation(spec, state, store, attestation, False)
def test_wrong_index_for_committee_signature(spec, state): attestation = get_valid_attestation(spec, state) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) attestation.data.index += 1 yield from run_attestation_processing(spec, state, attestation, False)
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_of_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 test_challenge_appended(spec, state): transition_to_valid_shard_slot(spec, state) transition_to(spec, state, state.slot + 1) # Make len(offset_slots) == 1 shard = 0 offset_slots = spec.get_offset_slots(state, shard) shard_transition = get_sample_shard_transition( spec, state.slot, [2**15 // 3] * len(offset_slots)) attestation = get_valid_attestation(spec, state, index=shard, signed=True, shard_transition=shard_transition) transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) _, _, _ = run_attestation_processing(spec, state, attestation) transition_to( spec, state, state.slot + spec.SLOTS_PER_EPOCH * spec.EPOCHS_PER_CUSTODY_PERIOD) challenge = get_valid_chunk_challenge(spec, state, attestation, shard_transition) yield from run_chunk_challenge_processing(spec, state, challenge)
def test_incorrect_target_min_inclusion_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=False) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) attestation.data.target.root = b'\x42' * 32 sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation)
def test_correct_epoch_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=True, on_time=False) next_slots(spec, state, spec.SLOTS_PER_EPOCH) yield from run_attestation_processing(spec, state, attestation)
def test_success_previous_epoch(spec, state): attestation = get_valid_attestation(spec, state, signed=True, on_time=False) next_epoch_via_block(spec, state) yield from run_attestation_processing(spec, state, attestation)
def test_invalid_index(spec, state): attestation = get_valid_attestation(spec, state) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) # Invalid index: off by one (with respect to valid range) on purpose attestation.data.index = spec.MAX_COMMITTEES_PER_SLOT yield from run_attestation_processing(spec, state, attestation, False)
def test_too_many_aggregation_bits(spec, state): attestation = get_valid_attestation(spec, state, signed=True) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) # one too many bits attestation.aggregation_bits.append(0b0) yield from run_attestation_processing(spec, state, attestation, False)
def test_incorrect_target_epoch_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=False) next_slots(spec, state, spec.SLOTS_PER_EPOCH) attestation.data.target.root = b'\x42' * 32 sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation)
def test_incorrect_head_sqrt_epoch_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=False) next_slots(spec, state, spec.integer_squareroot(spec.SLOTS_PER_EPOCH)) attestation.data.beacon_block_root = b'\x42' * 32 sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation)
def test_old_target_epoch(spec, state): assert spec.MIN_ATTESTATION_INCLUSION_DELAY < spec.SLOTS_PER_EPOCH * 2 attestation = get_valid_attestation(spec, state, signed=True) state.slot = spec.SLOTS_PER_EPOCH * 2 # target epoch will be too old to handle yield from run_attestation_processing(spec, state, attestation, False)
def test_after_epoch_slots(spec, state): attestation = get_valid_attestation(spec, state, signed=True) state.slot = spec.SLOTS_PER_EPOCH - 1 # increment past latest inclusion slot spec.process_slots(state, state.slot + 2) apply_empty_block(spec, state) yield from run_attestation_processing(spec, state, attestation, False)
def test_too_many_custody_bits(spec, state): attestation = get_valid_attestation(spec, state, signed=True) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY # one too many bits attestation.custody_bits.append(0b0) yield from run_attestation_processing(spec, state, attestation, False)
def test_bad_source_root(spec, state): attestation = get_valid_attestation(spec, state) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) attestation.data.source.root = b'\x42' * 32 sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation, False)
def test_new_source_epoch(spec, state): attestation = get_valid_attestation(spec, state) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) attestation.data.source.epoch += 1 sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation, False)