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_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_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_on_block_update_justified_checkpoint_within_safe_slots(spec, state): # Initialization store = get_genesis_forkchoice_store(spec, state) time = 0 spec.on_tick(store, time) next_epoch(spec, state) spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT) state, store, last_signed_block = apply_next_epoch_with_attestations(spec, state, store) next_epoch(spec, state) spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT) last_block_root = hash_tree_root(last_signed_block.message) # Mock the justified checkpoint just_state = store.block_states[last_block_root] new_justified = spec.Checkpoint( epoch=just_state.current_justified_checkpoint.epoch + 1, root=b'\x77' * 32, ) just_state.current_justified_checkpoint = new_justified block = build_empty_block_for_next_slot(spec, just_state) signed_block = state_transition_and_sign_block(spec, deepcopy(just_state), block) assert spec.get_current_slot(store) % spec.SLOTS_PER_EPOCH < spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED run_on_block(spec, store, signed_block) assert store.justified_checkpoint == new_justified
def test_update_justified_single_on_store_finalized_chain(spec, state): store = get_genesis_forkchoice_store(spec, state) # [Mock store.best_justified_checkpoint] # Create a block at epoch 1 next_epoch(spec, state) block = build_empty_block_for_next_slot(spec, state) state_transition_and_sign_block(spec, state, block) store.blocks[block.hash_tree_root()] = block.copy() store.block_states[block.hash_tree_root()] = state.copy() parent_block = block.copy() # To make compute_slots_since_epoch_start(current_slot) == 0, transition to the end of the epoch slot = state.slot + spec.SLOTS_PER_EPOCH - state.slot % spec.SLOTS_PER_EPOCH - 1 transition_to(spec, state, slot) # Create a block at the start of epoch 2 block = build_empty_block_for_next_slot(spec, state) # Mock state state.current_justified_checkpoint = spec.Checkpoint( epoch=spec.compute_epoch_at_slot(parent_block.slot), root=parent_block.hash_tree_root(), ) state_transition_and_sign_block(spec, state, block) store.blocks[block.hash_tree_root()] = block store.block_states[block.hash_tree_root()] = state # Mock store.best_justified_checkpoint store.best_justified_checkpoint = state.current_justified_checkpoint.copy() run_on_tick(spec, store, store.genesis_time + state.slot * spec.config.SECONDS_PER_SLOT, new_justified_checkpoint=True)
def test_shorter_chain_but_heavier_weight(spec, state): genesis_state = state.copy() # Initialization store = get_genesis_forkchoice_store(spec, state) anchor_root = get_anchor_root(spec, state) assert spec.get_head(store) == anchor_root # build longer tree long_state = genesis_state.copy() for _ 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_no_update_not_epoch_boundary(spec, state): store = get_genesis_forkchoice_store(spec, state) store.best_justified_checkpoint = spec.Checkpoint( epoch=store.justified_checkpoint.epoch + 1, root=b'\x55' * 32, ) run_on_tick(spec, store, store.time + spec.config.SECONDS_PER_SLOT)
def test_on_block_future_block(spec, state): # Initialization store = get_genesis_forkchoice_store(spec, state) # do not tick time # Fail receiving block of `GENESIS_SLOT + 1` slot block = build_empty_block_for_next_slot(spec, state) signed_block = state_transition_and_sign_block(spec, state, block) run_on_block(spec, store, signed_block, False)
def test_on_block_outside_safe_slots_and_multiple_better_justified( spec, state): # Initialization store = get_genesis_forkchoice_store(spec, state) time = 0 spec.on_tick(store, time) next_epoch(spec, state) spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT) state, store, last_signed_block = apply_next_epoch_with_attestations( spec, state, store) next_epoch(spec, state) spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT) last_block_root = hash_tree_root(last_signed_block.message) # Mock justified block in store just_block = build_empty_block_for_next_slot(spec, state) # Slot is same as justified checkpoint so does not trigger an override in the store just_block.slot = spec.compute_start_slot_at_epoch( store.justified_checkpoint.epoch) store.blocks[just_block.hash_tree_root()] = just_block # Step time past safe slots spec.on_tick( store, store.time + spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED * spec.SECONDS_PER_SLOT) assert spec.get_current_slot( store) % spec.SLOTS_PER_EPOCH >= spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED previously_justified = store.justified_checkpoint # Add a series of new blocks with "better" justifications best_justified_checkpoint = spec.Checkpoint(epoch=0) for i in range(3, 0, -1): just_state = store.block_states[last_block_root] new_justified = spec.Checkpoint( epoch=previously_justified.epoch + i, root=just_block.hash_tree_root(), ) if new_justified.epoch > best_justified_checkpoint.epoch: best_justified_checkpoint = new_justified just_state.current_justified_checkpoint = new_justified block = build_empty_block_for_next_slot(spec, just_state) signed_block = state_transition_and_sign_block(spec, deepcopy(just_state), block) run_on_block(spec, store, signed_block) assert store.justified_checkpoint == previously_justified # ensure the best from the series was stored assert store.best_justified_checkpoint == best_justified_checkpoint
def test_on_attestation_same_slot(spec, state): store = get_genesis_forkchoice_store(spec, state) time = store.time + spec.config.SECONDS_PER_SLOT 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 = get_valid_attestation(spec, state, slot=block.slot, signed=True) run_on_attestation(spec, state, store, attestation, False)
def test_update_justified_single(spec, state): store = get_genesis_forkchoice_store(spec, state) next_epoch = spec.get_current_epoch(state) + 1 next_epoch_start_slot = spec.compute_start_slot_at_epoch(next_epoch) seconds_until_next_epoch = next_epoch_start_slot * spec.SECONDS_PER_SLOT - store.time store.best_justified_checkpoint = spec.Checkpoint( epoch=store.justified_checkpoint.epoch + 1, root=b'\x55' * 32, ) run_on_tick(spec, store, store.time + seconds_until_next_epoch, True)
def initialize_store(spec, state, shards): store = get_genesis_forkchoice_store(spec, state) anchor_root = get_anchor_root(spec, state) assert spec.get_head(store) == anchor_root for shard in shards: shard_head_root = spec.get_shard_head(store, shard) assert shard_head_root == state.shard_states[shard].latest_block_root shard_store = store.shard_stores[shard] assert shard_store.block_states[shard_head_root].slot == 0 assert shard_store.block_states[shard_head_root] == state.shard_states[shard] return store
def test_no_update_same_slot_at_epoch_boundary(spec, state): store = get_genesis_forkchoice_store(spec, state) seconds_per_epoch = spec.config.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH store.best_justified_checkpoint = spec.Checkpoint( epoch=store.justified_checkpoint.epoch + 1, root=b'\x55' * 32, ) # set store time to already be at epoch boundary store.time = seconds_per_epoch run_on_tick(spec, store, store.time + 1)
def test_on_block_outside_safe_slots_but_finality(spec, state): # Initialization store = get_genesis_forkchoice_store(spec, state) time = 100 spec.on_tick(store, time) next_epoch(spec, state) spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT) state, store, last_signed_block = apply_next_epoch_with_attestations(spec, state, store) last_block_root = hash_tree_root(last_signed_block.message) # Mock fictitious justified checkpoint in store store.justified_checkpoint = spec.Checkpoint( epoch=spec.compute_epoch_at_slot(last_signed_block.message.slot), root=spec.Root("0x4a55535449464945440000000000000000000000000000000000000000000000") ) next_epoch(spec, state) spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT) # Create new higher justified checkpoint not in branch of store's justified checkpoint just_block = build_empty_block_for_next_slot(spec, state) store.blocks[just_block.hash_tree_root()] = just_block # Step time past safe slots spec.on_tick(store, store.time + spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED * spec.SECONDS_PER_SLOT) assert spec.get_current_slot(store) % spec.SLOTS_PER_EPOCH >= spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED # Mock justified and finalized update in state just_fin_state = store.block_states[last_block_root] new_justified = spec.Checkpoint( epoch=spec.compute_epoch_at_slot(just_block.slot) + 1, root=just_block.hash_tree_root(), ) assert new_justified.epoch > store.justified_checkpoint.epoch new_finalized = spec.Checkpoint( epoch=spec.compute_epoch_at_slot(just_block.slot), root=just_block.parent_root, ) assert new_finalized.epoch > store.finalized_checkpoint.epoch just_fin_state.current_justified_checkpoint = new_justified just_fin_state.finalized_checkpoint = new_finalized # Build and add block that includes the new justified/finalized info block = build_empty_block_for_next_slot(spec, just_fin_state) signed_block = state_transition_and_sign_block(spec, deepcopy(just_fin_state), block) run_on_block(spec, store, signed_block) assert store.finalized_checkpoint == new_finalized assert store.justified_checkpoint == new_justified
def test_on_block_outside_safe_slots_but_finality(spec, state): # Initialization store = get_genesis_forkchoice_store(spec, state) time = 100 spec.on_tick(store, time) next_epoch(spec, state) spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT) state, store, last_signed_block = apply_next_epoch_with_attestations( spec, state, store) next_epoch(spec, state) spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT) last_block_root = hash_tree_root(last_signed_block.message) # Mock justified block in store just_block = build_empty_block_for_next_slot(spec, state) # Slot is same as justified checkpoint so does not trigger an override in the store just_block.slot = spec.compute_start_slot_at_epoch( store.justified_checkpoint.epoch) store.blocks[just_block.hash_tree_root()] = just_block # Step time past safe slots spec.on_tick( store, store.time + spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED * spec.SECONDS_PER_SLOT) assert spec.get_current_slot( store) % spec.SLOTS_PER_EPOCH >= spec.SAFE_SLOTS_TO_UPDATE_JUSTIFIED # Mock justified and finalized update in state just_fin_state = store.block_states[last_block_root] new_justified = spec.Checkpoint( epoch=store.justified_checkpoint.epoch + 1, root=just_block.hash_tree_root(), ) new_finalized = spec.Checkpoint( epoch=store.finalized_checkpoint.epoch + 1, root=just_block.parent_root, ) just_fin_state.current_justified_checkpoint = new_justified just_fin_state.finalized_checkpoint = new_finalized # Build and add block that includes the new justified/finalized info block = build_empty_block_for_next_slot(spec, just_fin_state) signed_block = state_transition_and_sign_block(spec, deepcopy(just_fin_state), block) run_on_block(spec, store, signed_block) assert store.finalized_checkpoint == new_finalized assert store.justified_checkpoint == new_justified
def test_on_block_before_finalized(spec, state): # Initialization store = get_genesis_forkchoice_store(spec, state) time = 100 spec.on_tick(store, time) store.finalized_checkpoint = spec.Checkpoint( epoch=store.finalized_checkpoint.epoch + 2, root=store.finalized_checkpoint.root) # Fail receiving block of `GENESIS_SLOT + 1` slot block = build_empty_block_for_next_slot(spec, state) signed_block = state_transition_and_sign_block(spec, state, block) run_on_block(spec, store, signed_block, False)
def test_on_attestation_invalid_attestation(spec, state): store = get_genesis_forkchoice_store(spec, state) time = store.time + 3 * spec.config.SECONDS_PER_SLOT 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 = get_valid_attestation(spec, state, slot=block.slot, signed=True) # make invalid by using an invalid committee index attestation.data.index = spec.MAX_COMMITTEES_PER_SLOT * spec.SLOTS_PER_EPOCH run_on_attestation(spec, state, store, attestation, False)
def test_on_attestation_previous_epoch(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, signed=True) assert attestation.data.target.epoch == 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)
def test_no_update_new_justified_later_epoch(spec, state): store = get_genesis_forkchoice_store(spec, state) seconds_per_epoch = spec.config.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH store.best_justified_checkpoint = spec.Checkpoint( epoch=store.justified_checkpoint.epoch + 1, root=b'\x55' * 32, ) store.justified_checkpoint = spec.Checkpoint( epoch=store.best_justified_checkpoint.epoch + 1, root=b'\44' * 32, ) run_on_tick(spec, store, store.time + seconds_per_epoch)
def test_on_block_finalized_skip_slots(spec, state): # Initialization store = get_genesis_forkchoice_store(spec, state) time = 100 spec.on_tick(store, time) store.finalized_checkpoint = spec.Checkpoint( epoch=store.finalized_checkpoint.epoch + 2, root=store.finalized_checkpoint.root ) # Build block that includes the skipped slots up to finality in chain block = build_empty_block(spec, state, spec.compute_start_slot_at_epoch(store.finalized_checkpoint.epoch) + 2) signed_block = state_transition_and_sign_block(spec, state, block) spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT) run_on_block(spec, store, signed_block)
def test_on_block_bad_parent_root(spec, state): # Initialization store = get_genesis_forkchoice_store(spec, state) time = 100 spec.on_tick(store, time) # Fail receiving block of `GENESIS_SLOT + 1` slot block = build_empty_block_for_next_slot(spec, state) transition_unsigned_block(spec, state, block) block.state_root = state.hash_tree_root() block.parent_root = b'\x45' * 32 signed_block = sign_block(spec, state, block) run_on_block(spec, store, signed_block, False)
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_on_attestation_future_epoch(spec, state): store = get_genesis_forkchoice_store(spec, state) time = store.time + 3 * spec.config.SECONDS_PER_SLOT spec.on_tick(store, time) 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) # move state forward but not store next_epoch(spec, state) attestation = get_valid_attestation(spec, state, slot=state.slot, signed=True) run_on_attestation(spec, state, store, attestation, False)
def test_chain_no_attestations(spec, state): # Initialization store = get_genesis_forkchoice_store(spec, state) anchor_root = get_anchor_root(spec, state) assert spec.get_head(store) == anchor_root # On receiving a block of `GENESIS_SLOT + 1` slot block_1 = build_empty_block_for_next_slot(spec, state) signed_block_1 = state_transition_and_sign_block(spec, state, block_1) add_block_to_store(spec, store, signed_block_1) # On receiving a block of next epoch block_2 = build_empty_block_for_next_slot(spec, state) signed_block_2 = state_transition_and_sign_block(spec, state, block_2) add_block_to_store(spec, store, signed_block_2) assert spec.get_head(store) == spec.hash_tree_root(block_2)
def test_on_attestation_past_epoch(spec, state): store = get_genesis_forkchoice_store(spec, state) # move time forward 2 epochs time = store.time + 2 * spec.config.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH spec.on_tick(store, time) # create and store block from 3 epochs ago 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) # create attestation for past block attestation = get_valid_attestation(spec, state, slot=state.slot, signed=True) assert attestation.data.target.epoch == spec.GENESIS_EPOCH assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == spec.GENESIS_EPOCH + 2 run_on_attestation(spec, state, store, attestation, False)
def test_basic(spec, state): # Initialization store = get_genesis_forkchoice_store(spec, state) time = 100 spec.on_tick(store, time) assert store.time == time # On receiving a block of `GENESIS_SLOT + 1` slot block = build_empty_block_for_next_slot(spec, state) signed_block = state_transition_and_sign_block(spec, state, block) run_on_block(spec, store, signed_block) # On receiving a block of next epoch store.time = time + spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH block = build_empty_block(spec, state, state.slot + spec.SLOTS_PER_EPOCH) signed_block = state_transition_and_sign_block(spec, state, block) run_on_block(spec, store, signed_block)
def test_on_block_checkpoints(spec, state): # Initialization store = get_genesis_forkchoice_store(spec, state) time = 100 spec.on_tick(store, time) next_epoch(spec, state) spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT) state, store, last_signed_block = apply_next_epoch_with_attestations(spec, state, store) next_epoch(spec, state) spec.on_tick(store, store.time + state.slot * spec.SECONDS_PER_SLOT) last_block_root = hash_tree_root(last_signed_block.message) # Mock the finalized_checkpoint fin_state = store.block_states[last_block_root] fin_state.finalized_checkpoint = ( store.block_states[last_block_root].current_justified_checkpoint ) block = build_empty_block_for_next_slot(spec, fin_state) signed_block = state_transition_and_sign_block(spec, deepcopy(fin_state), block) run_on_block(spec, store, signed_block)
def test_split_tie_breaker_no_attestations(spec, state): genesis_state = state.copy() # Initialization store = get_genesis_forkchoice_store(spec, state) anchor_root = get_anchor_root(spec, state) assert spec.get_head(store) == anchor_root # block at slot 1 block_1_state = genesis_state.copy() block_1 = build_empty_block_for_next_slot(spec, block_1_state) signed_block_1 = state_transition_and_sign_block(spec, block_1_state, block_1) add_block_to_store(spec, store, signed_block_1) # additional block at slot 1 block_2_state = genesis_state.copy() block_2 = build_empty_block_for_next_slot(spec, block_2_state) block_2.body.graffiti = b'\x42' * 32 signed_block_2 = state_transition_and_sign_block(spec, block_2_state, block_2) add_block_to_store(spec, store, signed_block_2) highest_root = max(spec.hash_tree_root(block_1), spec.hash_tree_root(block_2)) assert spec.get_head(store) == highest_root
def test_genesis(spec, state): # Initialization store = get_genesis_forkchoice_store(spec, state) anchor_root = get_anchor_root(spec, state) assert spec.get_head(store) == anchor_root
def test_filtered_block_tree(spec, state): # Initialization store = get_genesis_forkchoice_store(spec, state) anchor_root = get_anchor_root(spec, state) # transition state past initial couple of epochs next_epoch(spec, state) next_epoch(spec, state) assert spec.get_head(store) == anchor_root # fill in attestations for entire epoch, justifying the recent epoch prev_state, signed_blocks, state = next_epoch_with_attestations(spec, state, True, False) attestations = [ attestation for signed_block in signed_blocks for attestation in signed_block.message.body.attestations ] assert state.current_justified_checkpoint.epoch > prev_state.current_justified_checkpoint.epoch # tick time forward and add blocks and attestations to store current_time = state.slot * spec.SECONDS_PER_SLOT + store.genesis_time spec.on_tick(store, current_time) for signed_block in signed_blocks: spec.on_block(store, signed_block) for attestation in attestations: spec.on_attestation(store, attestation) assert store.justified_checkpoint == state.current_justified_checkpoint # the last block in the branch should be the head expected_head_root = spec.hash_tree_root(signed_blocks[-1].message) assert spec.get_head(store) == expected_head_root # # create branch containing the justified block but not containing enough on # chain votes to justify that block # # build a chain without attestations off of previous justified block non_viable_state = store.block_states[store.justified_checkpoint.root].copy() # ensure that next wave of votes are for future epoch next_epoch(spec, non_viable_state) next_epoch(spec, non_viable_state) next_epoch(spec, non_viable_state) assert spec.get_current_epoch(non_viable_state) > store.justified_checkpoint.epoch # create rogue block that will be attested to in this non-viable branch rogue_block = build_empty_block_for_next_slot(spec, non_viable_state) signed_rogue_block = state_transition_and_sign_block(spec, non_viable_state, rogue_block) # create an epoch's worth of attestations for the rogue block next_epoch(spec, non_viable_state) attestations = [] for i in range(spec.SLOTS_PER_EPOCH): slot = rogue_block.slot + i for index in range(spec.get_committee_count_per_slot(non_viable_state, spec.compute_epoch_at_slot(slot))): attestation = get_valid_attestation(spec, non_viable_state, slot, index, signed=True) attestations.append(attestation) # tick time forward to be able to include up to the latest attestation current_time = (attestations[-1].data.slot + 1) * spec.SECONDS_PER_SLOT + store.genesis_time spec.on_tick(store, current_time) # include rogue block and associated attestations in the store spec.on_block(store, signed_rogue_block) for attestation in attestations: spec.on_attestation(store, attestation) # ensure that get_head still returns the head from the previous branch assert spec.get_head(store) == expected_head_root