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_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_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_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_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_non_zero_crosslink_data_root(spec, state): attestation = get_valid_attestation(spec, state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation.data.crosslink.data_root = b'\x42' * 32 sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation, False)
def test_source_root_is_target_root(spec, state): attestation = get_valid_attestation(spec, state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation.data.source_root = attestation.data.target_root sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation, False)
def test_non_empty_custody_bitfield(spec, state): attestation = get_valid_attestation(spec, state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation.custody_bitfield = deepcopy(attestation.aggregation_bitfield) sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation, False)
def test_incorrect_target_after_epoch_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=False) # increment past latest inclusion slot next_slots(spec, state, spec.SLOTS_PER_EPOCH + 1) attestation.data.target.root = b'\x42' * 32 sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation, False)
def test_wrong_shard(spec, state): attestation = get_valid_attestation(spec, state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation.data.crosslink.shard += 1 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)
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_inconsistent_bitfields(spec, state): attestation = get_valid_attestation(spec, state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation.custody_bitfield = deepcopy(attestation.aggregation_bitfield) + b'\x00' sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation, False)
def test_empty_aggregation_bitfield(spec, state): attestation = get_valid_attestation(spec, state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation.aggregation_bitfield = b'\x00' * len(attestation.aggregation_bitfield) sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation)
def test_empty_aggregation_bits(spec, state): attestation = get_valid_attestation(spec, state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY attestation.aggregation_bits = Bitlist[spec.MAX_VALIDATORS_PER_COMMITTEE]( *([0b0] * len(attestation.aggregation_bits))) sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation)
def test_invalid_shard(spec, state): attestation = get_valid_attestation(spec, state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY # off by one (with respect to valid range) on purpose attestation.data.crosslink.shard = spec.SHARD_COUNT sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation, False)
def test_mismatched_target_and_slot(spec, state): next_epoch_via_block(spec, state) next_epoch_via_block(spec, state) attestation = get_valid_attestation(spec, state, on_time=False) attestation.data.slot = attestation.data.slot - spec.SLOTS_PER_EPOCH sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation, False)
def test_inconsistent_bits(spec, state): attestation = get_valid_attestation(spec, state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY custody_bits = attestation.aggregation_bits[:] custody_bits.append(False) attestation.custody_bits = custody_bits sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation, False)
def test_too_few_aggregation_bits(spec, state): attestation = get_valid_attestation(spec, state) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) attestation.aggregation_bits = Bitlist[spec.MAX_VALIDATORS_PER_COMMITTEE]( *([0b1] + [0b0] * (len(attestation.aggregation_bits) - 1))) sign_attestation(spec, state, attestation) # one too few bits attestation.aggregation_bits = attestation.aggregation_bits[:-1] yield from run_attestation_processing(spec, state, attestation, False)
def get_valid_attester_slashing(state, signed_1=False, signed_2=False): attestation_1 = get_valid_attestation(state, signed=signed_1) attestation_2 = deepcopy(attestation_1) attestation_2.data.target_root = b'\x01' * 32 if signed_2: sign_attestation(state, attestation_2) return AttesterSlashing( attestation_1=convert_to_indexed(state, attestation_1), attestation_2=convert_to_indexed(state, attestation_2), )
def get_valid_attester_slashing(spec, state, signed_1=False, signed_2=False): attestation_1 = get_valid_attestation(spec, state, signed=signed_1) attestation_2 = attestation_1.copy() attestation_2.data.target.root = b'\x01' * 32 if signed_2: sign_attestation(spec, state, attestation_2) return spec.AttesterSlashing( attestation_1=spec.get_indexed_attestation(state, attestation_1), attestation_2=spec.get_indexed_attestation(state, attestation_2), )
def test_bad_crosslink_end_epoch(spec, state): state.slot = spec.SLOTS_PER_EPOCH - 1 next_epoch(spec, state) apply_empty_block(spec, state) attestation = get_valid_attestation(spec, state, signed=False) for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY): next_slot(spec, state) apply_empty_block(spec, state) attestation.data.crosslink.end_epoch += 1 sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation, False)
def test_double_late_crosslink(spec, state): if spec.get_epoch_committee_count( state, spec.get_current_epoch(state)) < spec.SHARD_COUNT: print( "warning: ignoring test, test-assumptions are incompatible with configuration" ) return next_epoch(spec, state) state.slot += 4 attestation_1 = get_valid_attestation(spec, state, signed=True) fill_aggregate_attestation(spec, state, attestation_1) # add attestation_1 to next epoch next_epoch(spec, state) add_attestation_to_state(spec, state, attestation_1, state.slot + 1) for _ in range(spec.SLOTS_PER_EPOCH): attestation_2 = get_valid_attestation(spec, state) if attestation_2.data.crosslink.shard == attestation_1.data.crosslink.shard: sign_attestation(spec, state, attestation_2) break next_slot(spec, state) apply_empty_block(spec, state) fill_aggregate_attestation(spec, state, attestation_2) # add attestation_2 in the next epoch after attestation_1 has # already updated the relevant crosslink next_epoch(spec, state) add_attestation_to_state(spec, state, attestation_2, state.slot + 1) assert len(state.previous_epoch_attestations) == 1 assert len(state.current_epoch_attestations) == 0 crosslink_deltas = spec.get_crosslink_deltas(state) yield from run_process_crosslinks(spec, state) shard = attestation_2.data.crosslink.shard # ensure that the current crosslinks were not updated by the second attestation assert state.previous_crosslinks[shard] == state.current_crosslinks[shard] # ensure no reward, only penalties for the failed crosslink for index in spec.get_crosslink_committee( state, attestation_2.data.target_epoch, attestation_2.data.crosslink.shard): assert crosslink_deltas[0][index] == 0 assert crosslink_deltas[1][index] > 0
def test_on_attestation_future_block(spec, state): store = get_genesis_forkchoice_store(spec, state) time = store.time + spec.config.SECONDS_PER_SLOT * 5 spec.on_tick(store, time) block = build_empty_block_for_next_slot(spec, state) signed_block = state_transition_and_sign_block(spec, state, block) spec.on_block(store, signed_block) # attestation for slot immediately prior to the block being attested to attestation = get_valid_attestation(spec, state, slot=block.slot - 1, signed=False) attestation.data.beacon_block_root = block.hash_tree_root() sign_attestation(spec, state, attestation) run_on_attestation(spec, state, store, attestation, False)
def test_old_source_epoch(spec, state): state.slot = spec.SLOTS_PER_EPOCH * 5 state.finalized_epoch = 2 state.previous_justified_epoch = 3 state.current_justified_epoch = 4 attestation = get_valid_attestation(spec, state, slot=(spec.SLOTS_PER_EPOCH * 3) + 1) # test logic sanity check: make sure the attestation is pointing to oldest known source epoch assert attestation.data.source_epoch == state.previous_justified_epoch # Now go beyond that, it will be invalid attestation.data.source_epoch -= 1 sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation, False)
def test_duplicate_participants_different_attestation_3(spec, state): """ Same attesters get two different attestations on chain for *different* inclusion delay Earlier attestation (by list order) has incorrect head, later is correct Note: although these are slashable, they can validly be included """ correct_attestation = get_valid_attestation(spec, state, signed=True) incorrect_attestation = correct_attestation.copy() incorrect_attestation.data.beacon_block_root = b'\x42' * 32 sign_attestation(spec, state, incorrect_attestation) indexed_attestation = spec.get_indexed_attestation(state, correct_attestation) participants = get_indexed_attestation_participants( spec, indexed_attestation) assert len(participants) > 0 single_correct_state = state.copy() dup_state = state.copy() inclusion_slot = state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY add_attestations_to_state(spec, single_correct_state, [correct_attestation], inclusion_slot) add_attestations_to_state(spec, dup_state, [incorrect_attestation], inclusion_slot) add_attestations_to_state(spec, dup_state, [correct_attestation], inclusion_slot + 1) next_epoch(spec, single_correct_state) next_epoch(spec, dup_state) # Run non-duplicate inclusion rewards for comparison. Do not yield test vectors for _ in run_process_rewards_and_penalties(spec, single_correct_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_correct_state.balances[index] # Inclusion delay does not take into account correctness so equal reward assert single_correct_state.balances[index] == dup_state.balances[ index]
def test_on_attestation_mismatched_target_and_slot(spec, state): store = get_genesis_forkchoice_store(spec, state) spec.on_tick(store, store.time + spec.config.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH) block = build_empty_block_for_next_slot(spec, state) signed_block = state_transition_and_sign_block(spec, state, block) # store block in store spec.on_block(store, signed_block) attestation = get_valid_attestation(spec, state, slot=block.slot) attestation.data.target.epoch += 1 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 assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == spec.GENESIS_EPOCH + 1 run_on_attestation(spec, state, store, attestation, False)
def sign_attestation(spec, state, attestation): if not any(attestation.custody_bits_blocks): phase0_attestations.sign_attestation(spec, state, attestation) return committee = spec.get_beacon_committee(state, attestation.data.slot, attestation.data.index) signatures = [] for block_index, custody_bits in enumerate( attestation.custody_bits_blocks): for participant, abit, cbit in zip(committee, attestation.aggregation_bits, custody_bits): if not abit: continue signatures.append( get_attestation_custody_signature(spec, state, attestation.data, block_index, cbit, privkeys[participant])) attestation.signature = bls.Aggregate(signatures)
def test_wrong_end_epoch_with_max_epochs_per_crosslink(spec, state): # Do not run mainnet (64 epochs), that would mean the equivalent of ~7 hours chain simulation. if spec.MAX_EPOCHS_PER_CROSSLINK > 4: return for _ in range(spec.MAX_EPOCHS_PER_CROSSLINK + 2): next_epoch(spec, state) apply_empty_block(spec, state) attestation = get_valid_attestation(spec, state) data = attestation.data # test logic sanity check: make sure the attestation only includes MAX_EPOCHS_PER_CROSSLINK epochs assert data.crosslink.end_epoch - data.crosslink.start_epoch == spec.MAX_EPOCHS_PER_CROSSLINK # Now change it to be different data.crosslink.end_epoch += 1 sign_attestation(spec, state, attestation) for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY): next_slot(spec, state) apply_empty_block(spec, state) yield from run_attestation_processing(spec, state, attestation, False)
def test_invalid_current_source_root(spec, state): state.slot = spec.SLOTS_PER_EPOCH * 5 state.finalized_epoch = 2 state.previous_justified_epoch = 3 state.previous_justified_root = b'\x01' * 32 state.current_justified_epoch = 4 state.current_justified_root = b'\xff' * 32 attestation = get_valid_attestation(spec, state, slot=(spec.SLOTS_PER_EPOCH * 3) + 1) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY # Test logic sanity checks: assert state.current_justified_root != state.previous_justified_root assert attestation.data.source_root == state.previous_justified_root # Make attestation source root invalid: should be previous justified, not current one attestation.data.source_root = state.current_justified_root sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation, False)