def test_incorrect_head_and_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.beacon_block_root = b'\x42' * 32 attestation.data.target.root = b'\x42' * 32 sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation)
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)
def test_process_light_client_update_timeout(spec, state): store = initialize_light_client_store(spec, state) # Forward to next sync committee period next_slots(spec, state, spec.UPDATE_TIMEOUT) snapshot_period = spec.compute_sync_committee_period( spec.compute_epoch_at_slot(store.optimistic_header.slot)) update_period = spec.compute_sync_committee_period( spec.compute_epoch_at_slot(state.slot)) assert snapshot_period + 1 == update_period block = build_empty_block_for_next_slot(spec, state) signed_block = state_transition_and_sign_block(spec, state, block) block_header = spec.BeaconBlockHeader( slot=signed_block.message.slot, proposer_index=signed_block.message.proposer_index, parent_root=signed_block.message.parent_root, state_root=signed_block.message.state_root, body_root=signed_block.message.body.hash_tree_root(), ) # Sync committee signing the finalized_block_header sync_aggregate = get_sync_aggregate(spec, state, block_header, block_root=spec.Root( block_header.hash_tree_root())) # Sync committee is updated next_sync_committee_branch = build_proof(state.get_backing(), spec.NEXT_SYNC_COMMITTEE_INDEX) # Finality is unchanged finality_header = spec.BeaconBlockHeader() finality_branch = [ spec.Bytes32() for _ in range(spec.floorlog2(spec.FINALIZED_ROOT_INDEX)) ] update = spec.LightClientUpdate( attested_header=block_header, next_sync_committee=state.next_sync_committee, next_sync_committee_branch=next_sync_committee_branch, finalized_header=finality_header, finality_branch=finality_branch, sync_aggregate=sync_aggregate, fork_version=state.fork.current_version, ) pre_store = deepcopy(store) spec.process_light_client_update(store, update, state.slot, state.genesis_validators_root) assert store.current_max_active_participants > 0 assert store.optimistic_header == update.attested_header assert store.best_valid_update == update assert store.finalized_header == pre_store.finalized_header
def test_incorrect_head_and_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.beacon_block_root = b'\x42' * 32 attestation.data.target.root = b'\x42' * 32 sign_attestation(spec, state, attestation) yield from run_attestation_processing(spec, state, attestation, False)
def test_correct_after_epoch_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=True, on_time=False) # increment past latest inclusion slot next_slots(spec, state, spec.SLOTS_PER_EPOCH + 1) yield from run_attestation_processing(spec, state, attestation, False)
def test_wrong_index_for_slot_0(spec, state): reduce_state_committee_count_from_max(spec, state) attestation = get_valid_attestation(spec, state) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) # Invalid index: current committees per slot is less than the max attestation.data.index = spec.MAX_COMMITTEES_PER_SLOT - 1 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, on_time=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, on_time=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, on_time=False) next_slots(spec, state, spec.SLOTS_PER_EPOCH * 2) # target epoch will be too old to handle yield from run_attestation_processing(spec, state, attestation, False)
def test_wrong_index_for_slot_1(spec, state): reduce_state_committee_count_from_max(spec, state) current_epoch = spec.get_current_epoch(state) committee_count = spec.get_committee_count_per_slot(state, current_epoch) attestation = get_valid_attestation(spec, state, index=0) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) # Invalid index: off by one attestation.data.index = committee_count 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 test_wrong_index_for_slot(spec, state): while spec.get_committee_count_at_slot(state, state.slot) >= spec.MAX_COMMITTEES_PER_SLOT: state.validators = state.validators[:len(state.validators) // 2] state.balances = state.balances[:len(state.balances) // 2] index = spec.MAX_COMMITTEES_PER_SLOT - 1 attestation = get_valid_attestation(spec, state) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) attestation.data.index = index yield from run_attestation_processing(spec, state, attestation, False)
def test_old_source_epoch(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH * 5) state.finalized_checkpoint.epoch = 2 state.previous_justified_checkpoint.epoch = 3 state.current_justified_checkpoint.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_checkpoint.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_on_block_finalized_skip_slots_not_in_skip_chain(spec, state): """ Test case was originally from https://github.com/ethereum/consensus-specs/pull/1579 And then rewrote largely. """ test_steps = [] # Initialization store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state) yield 'anchor_state', state yield 'anchor_block', anchor_block current_time = state.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, current_time, test_steps) assert store.time == current_time # Fill epoch 0 and the first slot of epoch 1 state, store, _ = yield from apply_next_slots_with_attestations( spec, state, store, spec.SLOTS_PER_EPOCH, True, False, test_steps) # Skip the rest slots of epoch 1 and the first slot of epoch 2 next_slots(spec, state, spec.SLOTS_PER_EPOCH) # Fill epoch 3 and 4 for _ in range(2): state, store, _ = yield from apply_next_epoch_with_attestations( spec, state, store, True, True, test_steps=test_steps) # Now we get finalized epoch 2, where `compute_start_slot_at_epoch(2)` is a skipped slot assert state.finalized_checkpoint.epoch == store.finalized_checkpoint.epoch == 2 assert store.finalized_checkpoint.root == spec.get_block_root( state, 1) == spec.get_block_root(state, 2) assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 assert store.justified_checkpoint == state.current_justified_checkpoint # Now build a block after the block of the finalized **root** # Includes finalized block in chain, but does not include finalized skipped slots another_state = store.block_states[store.finalized_checkpoint.root].copy() assert another_state.slot == spec.compute_start_slot_at_epoch( store.finalized_checkpoint.epoch - 1) block = build_empty_block_for_next_slot(spec, another_state) signed_block = state_transition_and_sign_block(spec, another_state, block) yield from tick_and_add_block(spec, store, signed_block, test_steps, valid=False) yield 'steps', test_steps
def test_future_target_epoch(spec, state): assert spec.MIN_ATTESTATION_INCLUSION_DELAY < spec.SLOTS_PER_EPOCH * 2 attestation = get_valid_attestation(spec, state) participants = spec.get_attesting_indices(state, attestation.data, attestation.aggregation_bits) attestation.data.target.epoch = spec.get_current_epoch( state) + 1 # target epoch will be too new to handle # manually add signature for correct participants attestation.signature = sign_aggregate_attestation(spec, state, attestation.data, participants) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) yield from run_attestation_processing(spec, state, 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_on_block_outside_safe_slots_but_finality(spec, state): """ Test `should_update_justified_checkpoint` case - compute_slots_since_epoch_start(get_current_slot(store)) > SAFE_SLOTS_TO_UPDATE_JUSTIFIED - new_justified_checkpoint and store.justified_checkpoint.root are NOT conflicting Thus should_update_justified_checkpoint returns True. Part of this script is similar to `test_new_justified_is_later_than_store_justified`. """ test_steps = [] # Initialization store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state) yield 'anchor_state', state yield 'anchor_block', anchor_block current_time = state.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, current_time, test_steps) assert store.time == current_time # Skip epoch 0 next_epoch(spec, state) # Fill epoch 1 to 3, attest current epoch for _ in range(3): state, store, _ = yield from apply_next_epoch_with_attestations( spec, state, store, True, False, test_steps=test_steps) assert state.finalized_checkpoint.epoch == store.finalized_checkpoint.epoch == 2 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 # Skip epoch 4-6 for _ in range(3): next_epoch(spec, state) # epoch 7 state, store, _ = yield from apply_next_epoch_with_attestations( spec, state, store, True, True, test_steps=test_steps) assert state.finalized_checkpoint.epoch == 2 assert state.current_justified_checkpoint.epoch == 7 # epoch 8, attest the first 5 blocks state, store, _ = yield from apply_next_slots_with_attestations( spec, state, store, 5, True, True, test_steps) assert state.finalized_checkpoint.epoch == store.finalized_checkpoint.epoch == 2 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 7 # Propose a block at epoch 9, 5th slot next_epoch(spec, state) next_slots(spec, state, 4) signed_block = state_transition_with_full_attestations_block( spec, state, True, True) yield from tick_and_add_block(spec, store, signed_block, test_steps) assert state.finalized_checkpoint.epoch == store.finalized_checkpoint.epoch == 2 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 7 # Propose an empty block at epoch 10, SAFE_SLOTS_TO_UPDATE_JUSTIFIED + 2 slot # This block would trigger justification and finality updates on store next_epoch(spec, state) next_slots(spec, state, 4) block = build_empty_block_for_next_slot(spec, state) signed_block = state_transition_and_sign_block(spec, state, block) assert state.finalized_checkpoint.epoch == 7 assert state.current_justified_checkpoint.epoch == 8 # Step time past safe slots and run on_block if store.time < spec.compute_time_at_slot(state, signed_block.message.slot): time = store.genesis_time + signed_block.message.slot * spec.config.SECONDS_PER_SLOT on_tick_and_append_step(spec, store, time, test_steps) assert spec.get_current_slot( store) % spec.SLOTS_PER_EPOCH >= spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED yield from add_block(spec, store, signed_block, test_steps) # Ensure justified_checkpoint finality has been changed assert store.finalized_checkpoint.epoch == 7 assert store.finalized_checkpoint == state.finalized_checkpoint assert store.justified_checkpoint.epoch == 8 assert store.justified_checkpoint == state.current_justified_checkpoint yield 'steps', test_steps
def test_success_multi_proposer_index_iterations(spec, state): next_slots(spec, state, spec.SLOTS_PER_EPOCH * 2) attestation = get_valid_attestation(spec, state, signed=True) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) yield from run_attestation_processing(spec, state, attestation)
def test_correct_min_inclusion_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=True) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) yield from run_attestation_processing(spec, state, attestation)
def test_process_light_client_update_finality_updated(spec, state): pre_snapshot = spec.LightClientSnapshot( header=spec.BeaconBlockHeader(), current_sync_committee=state.current_sync_committee, next_sync_committee=state.next_sync_committee, ) store = spec.LightClientStore(snapshot=pre_snapshot, valid_updates=[]) # Change finality blocks = [] next_slots(spec, state, spec.SLOTS_PER_EPOCH * 2) for epoch in range(3): prev_state, new_blocks, state = next_epoch_with_attestations( spec, state, True, True) blocks += new_blocks # Ensure that finality checkpoint has changed assert state.finalized_checkpoint.epoch == 3 # Ensure that it's same period snapshot_period = spec.compute_epoch_at_slot( pre_snapshot.header.slot) // spec.EPOCHS_PER_SYNC_COMMITTEE_PERIOD update_period = spec.compute_epoch_at_slot( state.slot) // spec.EPOCHS_PER_SYNC_COMMITTEE_PERIOD assert snapshot_period == update_period # Updated sync_committee and finality next_sync_committee_branch = [ spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX)) ] finalized_block_header = blocks[spec.SLOTS_PER_EPOCH - 1].message assert finalized_block_header.slot == spec.compute_start_slot_at_epoch( state.finalized_checkpoint.epoch) assert finalized_block_header.hash_tree_root( ) == state.finalized_checkpoint.root finality_branch = build_proof(state.get_backing(), spec.FINALIZED_ROOT_INDEX) # Build block header block = build_empty_block(spec, state) block_header = spec.BeaconBlockHeader( slot=block.slot, proposer_index=block.proposer_index, parent_root=block.parent_root, state_root=state.hash_tree_root(), body_root=block.body.hash_tree_root(), ) # Sync committee signing the finalized_block_header committee = spec.get_sync_committee_indices(state, spec.get_current_epoch(state)) sync_committee_bits = [True] * len(committee) sync_committee_signature = compute_aggregate_sync_committee_signature( spec, state, block_header.slot, committee, block_root=spec.Root(block_header.hash_tree_root()), ) update = spec.LightClientUpdate( header=finalized_block_header, next_sync_committee=state.next_sync_committee, next_sync_committee_branch=next_sync_committee_branch, finality_header=block_header, # block_header is the signed header finality_branch=finality_branch, sync_committee_bits=sync_committee_bits, sync_committee_signature=sync_committee_signature, fork_version=state.fork.current_version, ) spec.process_light_client_update(store, update, state.slot, state.genesis_validators_root) # snapshot has been updated assert len(store.valid_updates) == 0 assert store.snapshot.header == update.header
def test_success(spec, state): attestation = get_valid_attestation(spec, state, signed=True) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) yield from run_attestation_processing(spec, state, attestation)
def test_process_light_client_update_timeout(spec, state): pre_snapshot = spec.LightClientSnapshot( header=spec.BeaconBlockHeader(), current_sync_committee=state.current_sync_committee, next_sync_committee=state.next_sync_committee, ) store = spec.LightClientStore(snapshot=pre_snapshot, valid_updates=[]) # Forward to next sync committee period next_slots(spec, state, spec.SLOTS_PER_EPOCH * (spec.EPOCHS_PER_SYNC_COMMITTEE_PERIOD)) snapshot_period = spec.compute_epoch_at_slot( pre_snapshot.header.slot) // spec.EPOCHS_PER_SYNC_COMMITTEE_PERIOD update_period = spec.compute_epoch_at_slot( state.slot) // spec.EPOCHS_PER_SYNC_COMMITTEE_PERIOD assert snapshot_period + 1 == update_period block = build_empty_block_for_next_slot(spec, state) signed_block = state_transition_and_sign_block(spec, state, block) block_header = spec.BeaconBlockHeader( slot=signed_block.message.slot, proposer_index=signed_block.message.proposer_index, parent_root=signed_block.message.parent_root, state_root=signed_block.message.state_root, body_root=signed_block.message.body.hash_tree_root(), ) # Sync committee signing the finalized_block_header committee = spec.get_sync_committee_indices(state, spec.get_current_epoch(state)) sync_committee_bits = [True] * len(committee) sync_committee_signature = compute_aggregate_sync_committee_signature( spec, state, block_header.slot, committee, block_root=spec.Root(block_header.hash_tree_root()), ) # Sync committee is updated next_sync_committee_branch = build_proof(state.get_backing(), spec.NEXT_SYNC_COMMITTEE_INDEX) # Finality is unchanged finality_header = spec.BeaconBlockHeader() finality_branch = [ spec.Bytes32() for _ in range(spec.floorlog2(spec.FINALIZED_ROOT_INDEX)) ] update = spec.LightClientUpdate( header=block_header, next_sync_committee=state.next_sync_committee, next_sync_committee_branch=next_sync_committee_branch, finality_header=finality_header, finality_branch=finality_branch, sync_committee_bits=sync_committee_bits, sync_committee_signature=sync_committee_signature, fork_version=state.fork.current_version, ) spec.process_light_client_update(store, update, state.slot, state.genesis_validators_root) # snapshot has been updated assert len(store.valid_updates) == 0 assert store.snapshot.header == update.header
def test_correct_epoch_delay(spec, state): attestation = get_valid_attestation(spec, state, signed=True) next_slots(spec, state, spec.SLOTS_PER_EPOCH) yield from run_attestation_processing(spec, state, attestation)
def test_proposer_boost_correct_head(spec, state): test_steps = [] genesis_state = state.copy() # Initialization store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state) yield 'anchor_state', state yield 'anchor_block', anchor_block anchor_root = get_anchor_root(spec, state) assert spec.get_head(store) == anchor_root test_steps.append( {'checks': { 'head': get_formatted_head_output(spec, store), }}) # Build block that serves as head ONLY on timely arrival, and ONLY in that slot state_1 = genesis_state.copy() next_slots(spec, state_1, 3) block_1 = build_empty_block_for_next_slot(spec, state_1) signed_block_1 = state_transition_and_sign_block(spec, state_1, block_1) # Build block that serves as current head, and remains the head after block_1.slot state_2 = genesis_state.copy() next_slots(spec, state_2, 2) block_2 = build_empty_block_for_next_slot(spec, state_2) signed_block_2 = state_transition_and_sign_block(spec, state_2.copy(), block_2) while spec.hash_tree_root(block_1) >= spec.hash_tree_root(block_2): block_2.body.graffiti = spec.Bytes32( hex(rng.getrandbits(8 * 32))[2:].zfill(64)) signed_block_2 = state_transition_and_sign_block( spec, state_2.copy(), block_2) assert spec.hash_tree_root(block_1) < spec.hash_tree_root(block_2) # Tick to block_1 slot time time = store.genesis_time + block_1.slot * spec.config.SECONDS_PER_SLOT on_tick_and_append_step(spec, store, time, test_steps) # Process block_2 yield from add_block(spec, store, signed_block_2, test_steps) assert store.proposer_boost_root == spec.Root() assert spec.get_head(store) == spec.hash_tree_root(block_2) # Process block_1 on timely arrival # The head should temporarily change to block_1 yield from add_block(spec, store, signed_block_1, test_steps) assert store.proposer_boost_root == spec.hash_tree_root(block_1) assert spec.get_head(store) == spec.hash_tree_root(block_1) # After block_1.slot, the head should revert to block_2 time = store.genesis_time + (block_1.slot + 1) * spec.config.SECONDS_PER_SLOT on_tick_and_append_step(spec, store, time, test_steps) assert store.proposer_boost_root == spec.Root() assert spec.get_head(store) == spec.hash_tree_root(block_2) test_steps.append( {'checks': { 'head': get_formatted_head_output(spec, store), }}) yield 'steps', test_steps
def test_process_light_client_update_finality_updated(spec, state): store = initialize_light_client_store(spec, state) # Change finality blocks = [] next_slots(spec, state, spec.SLOTS_PER_EPOCH * 2) for epoch in range(3): prev_state, new_blocks, state = next_epoch_with_attestations( spec, state, True, True) blocks += new_blocks # Ensure that finality checkpoint has changed assert state.finalized_checkpoint.epoch == 3 # Ensure that it's same period snapshot_period = spec.compute_sync_committee_period( spec.compute_epoch_at_slot(store.optimistic_header.slot)) update_period = spec.compute_sync_committee_period( spec.compute_epoch_at_slot(state.slot)) assert snapshot_period == update_period # Updated sync_committee and finality next_sync_committee_branch = [ spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX)) ] finalized_block_header = blocks[spec.SLOTS_PER_EPOCH - 1].message assert finalized_block_header.slot == spec.compute_start_slot_at_epoch( state.finalized_checkpoint.epoch) assert finalized_block_header.hash_tree_root( ) == state.finalized_checkpoint.root finality_branch = build_proof(state.get_backing(), spec.FINALIZED_ROOT_INDEX) # Build block header block = build_empty_block(spec, state) block_header = spec.BeaconBlockHeader( slot=block.slot, proposer_index=block.proposer_index, parent_root=block.parent_root, state_root=state.hash_tree_root(), body_root=block.body.hash_tree_root(), ) # Sync committee signing the finalized_block_header sync_aggregate = get_sync_aggregate(spec, state, block_header, block_root=spec.Root( block_header.hash_tree_root())) update = spec.LightClientUpdate( attested_header=block_header, next_sync_committee=state.next_sync_committee, next_sync_committee_branch=next_sync_committee_branch, finalized_header=finalized_block_header, finality_branch=finality_branch, sync_aggregate=sync_aggregate, fork_version=state.fork.current_version, ) spec.process_light_client_update(store, update, state.slot, state.genesis_validators_root) assert store.current_max_active_participants > 0 assert store.optimistic_header == update.attested_header assert store.finalized_header == update.finalized_header assert store.best_valid_update is None
def test_invalid_attestation_signature(spec, state): attestation = get_valid_attestation(spec, state) next_slots(spec, state, spec.MIN_ATTESTATION_INCLUSION_DELAY) yield from run_attestation_processing(spec, state, attestation, False)
def test_new_justified_is_later_than_store_justified(spec, state): """ J: Justified F: Finalized fork_1_state (forked from genesis): epoch [0] <- [1] <- [2] <- [3] <- [4] F J fork_2_state (forked from fork_1_state's epoch 2): epoch └──── [3] <- [4] <- [5] <- [6] F J fork_3_state (forked from genesis): [0] <- [1] <- [2] <- [3] <- [4] <- [5] F J """ # The 1st fork, from genesis fork_1_state = state.copy() # The 3rd fork, from genesis fork_3_state = state.copy() test_steps = [] # Initialization store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state) yield 'anchor_state', state yield 'anchor_block', anchor_block current_time = state.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, current_time, test_steps) assert store.time == current_time # ----- Process fork_1_state # Skip epoch 0 next_epoch(spec, fork_1_state) # Fill epoch 1 with previous epoch attestations fork_1_state, store, _ = yield from apply_next_epoch_with_attestations( spec, fork_1_state, store, False, True, test_steps=test_steps) # Fork `fork_2_state` at the start of epoch 2 fork_2_state = fork_1_state.copy() assert spec.get_current_epoch(fork_2_state) == 2 # Skip epoch 2 next_epoch(spec, fork_1_state) # # Fill epoch 3 & 4 with previous epoch attestations for _ in range(2): fork_1_state, store, _ = yield from apply_next_epoch_with_attestations( spec, fork_1_state, store, False, True, test_steps=test_steps) assert fork_1_state.finalized_checkpoint.epoch == store.finalized_checkpoint.epoch == 0 assert fork_1_state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 assert store.justified_checkpoint == fork_1_state.current_justified_checkpoint # ------ fork_2_state: Create a chain to set store.best_justified_checkpoint # NOTE: The goal is to make `store.best_justified_checkpoint.epoch > store.justified_checkpoint.epoch` all_blocks = [] # Proposed an empty block at epoch 2, 1st slot block = build_empty_block_for_next_slot(spec, fork_2_state) signed_block = state_transition_and_sign_block(spec, fork_2_state, block) yield from tick_and_add_block(spec, store, signed_block, test_steps) assert fork_2_state.current_justified_checkpoint.epoch == 0 # Skip to epoch 4 for _ in range(2): next_epoch(spec, fork_2_state) assert fork_2_state.current_justified_checkpoint.epoch == 0 # Propose a block at epoch 4, 5th slot # Propose a block at epoch 5, 5th slot for _ in range(2): next_epoch(spec, fork_2_state) next_slots(spec, fork_2_state, 4) signed_block = state_transition_with_full_attestations_block( spec, fork_2_state, True, True) yield from tick_and_add_block(spec, store, signed_block, test_steps) assert fork_2_state.current_justified_checkpoint.epoch == 0 # Propose a block at epoch 6, SAFE_SLOTS_TO_UPDATE_JUSTIFIED + 2 slot next_epoch(spec, fork_2_state) next_slots(spec, fork_2_state, spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED + 2) signed_block = state_transition_with_full_attestations_block( spec, fork_2_state, True, True) assert fork_2_state.finalized_checkpoint.epoch == 0 assert fork_2_state.current_justified_checkpoint.epoch == 5 # Check SAFE_SLOTS_TO_UPDATE_JUSTIFIED time = store.genesis_time + fork_2_state.slot * spec.config.SECONDS_PER_SLOT on_tick_and_append_step(spec, store, time, test_steps) assert spec.compute_slots_since_epoch_start( spec.get_current_slot(store)) >= spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED # Run on_block yield from add_block(spec, store, signed_block, test_steps) assert store.finalized_checkpoint.epoch == 0 assert store.justified_checkpoint.epoch == 3 assert store.best_justified_checkpoint.epoch == 5 # ------ fork_3_state: Create another chain to test the # "Update justified if new justified is later than store justified" case all_blocks = [] for _ in range(3): next_epoch(spec, fork_3_state) # epoch 3 _, signed_blocks, fork_3_state = next_epoch_with_attestations( spec, fork_3_state, True, True) all_blocks += signed_blocks assert fork_3_state.finalized_checkpoint.epoch == 0 # epoch 4, attest the first 5 blocks _, blocks, fork_3_state = next_slots_with_attestations( spec, fork_3_state, 5, True, True) all_blocks += blocks.copy() assert fork_3_state.finalized_checkpoint.epoch == 0 # Propose a block at epoch 5, 5th slot next_epoch(spec, fork_3_state) next_slots(spec, fork_3_state, 4) signed_block = state_transition_with_full_block(spec, fork_3_state, True, True) all_blocks.append(signed_block.copy()) assert fork_3_state.finalized_checkpoint.epoch == 0 # Propose a block at epoch 6, 5th slot next_epoch(spec, fork_3_state) next_slots(spec, fork_3_state, 4) signed_block = state_transition_with_full_block(spec, fork_3_state, True, True) all_blocks.append(signed_block.copy()) assert fork_3_state.finalized_checkpoint.epoch == 3 assert fork_3_state.current_justified_checkpoint.epoch == 4 # Apply blocks of `fork_3_state` to `store` for block in all_blocks: if store.time < spec.compute_time_at_slot(fork_2_state, block.message.slot): time = store.genesis_time + block.message.slot * spec.config.SECONDS_PER_SLOT on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, block, test_steps) assert store.finalized_checkpoint == fork_3_state.finalized_checkpoint assert store.justified_checkpoint == fork_3_state.current_justified_checkpoint assert store.justified_checkpoint != store.best_justified_checkpoint assert store.best_justified_checkpoint == fork_2_state.current_justified_checkpoint yield 'steps', test_steps
def test_discard_equivocations(spec, state): test_steps = [] genesis_state = state.copy() # Initialization store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state) yield 'anchor_state', state yield 'anchor_block', anchor_block anchor_root = get_anchor_root(spec, state) assert spec.get_head(store) == anchor_root test_steps.append( {'checks': { 'head': get_formatted_head_output(spec, store), }}) # Build block that serves as head before discarding equivocations state_1 = genesis_state.copy() next_slots(spec, state_1, 3) block_1 = build_empty_block_for_next_slot(spec, state_1) signed_block_1 = state_transition_and_sign_block(spec, state_1, block_1) # Build equivocating attestations to feed to store state_eqv = state_1.copy() block_eqv = apply_empty_block(spec, state_eqv, state_eqv.slot + 1) attestation_eqv = get_valid_attestation(spec, state_eqv, slot=block_eqv.slot, signed=True) next_slots(spec, state_1, 1) attestation = get_valid_attestation(spec, state_1, slot=block_eqv.slot, signed=True) assert spec.is_slashable_attestation_data(attestation.data, attestation_eqv.data) indexed_attestation = spec.get_indexed_attestation(state_1, attestation) indexed_attestation_eqv = spec.get_indexed_attestation( state_eqv, attestation_eqv) attester_slashing = spec.AttesterSlashing( attestation_1=indexed_attestation, attestation_2=indexed_attestation_eqv) # Build block that serves as head after discarding equivocations state_2 = genesis_state.copy() next_slots(spec, state_2, 2) block_2 = build_empty_block_for_next_slot(spec, state_2) signed_block_2 = state_transition_and_sign_block(spec, state_2.copy(), block_2) while spec.hash_tree_root(block_1) >= spec.hash_tree_root(block_2): block_2.body.graffiti = spec.Bytes32( hex(rng.getrandbits(8 * 32))[2:].zfill(64)) signed_block_2 = state_transition_and_sign_block( spec, state_2.copy(), block_2) assert spec.hash_tree_root(block_1) < spec.hash_tree_root(block_2) # Tick to (block_eqv.slot + 2) slot time time = store.genesis_time + (block_eqv.slot + 2) * spec.config.SECONDS_PER_SLOT on_tick_and_append_step(spec, store, time, test_steps) # Process block_2 yield from add_block(spec, store, signed_block_2, test_steps) assert store.proposer_boost_root == spec.Root() assert spec.get_head(store) == spec.hash_tree_root(block_2) # Process block_1 # The head should remain block_2 yield from add_block(spec, store, signed_block_1, test_steps) assert store.proposer_boost_root == spec.Root() assert spec.get_head(store) == spec.hash_tree_root(block_2) # Process attestation # The head should change to block_1 yield from add_attestation(spec, store, attestation, test_steps) assert spec.get_head(store) == spec.hash_tree_root(block_1) # Process attester_slashing # The head should revert to block_2 yield from add_attester_slashing(spec, store, attester_slashing, test_steps) assert spec.get_head(store) == spec.hash_tree_root(block_2) test_steps.append( {'checks': { 'head': get_formatted_head_output(spec, store), }}) yield 'steps', test_steps
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)