def create_beacon_block_with_shard_transition( spec, state, store, shard, shard_blocks_buffer, is_checking_pending_shard_blocks=True): beacon_block = build_empty_block(spec, state, slot=state.slot + 1) committee_index = get_committee_index_of_shard(spec, state, state.slot, shard) has_shard_committee = committee_index is not None # has committee of `shard` at this slot beacon_block = build_empty_block(spec, state, slot=state.slot + 1) # If next slot has committee of `shard`, add `shard_transtion` to the proposing beacon block if has_shard_committee and len(shard_blocks_buffer) > 0: # Sanity check `get_pending_shard_blocks` # Assert that the pending shard blocks set in the store equal to shard_blocks_buffer if is_checking_pending_shard_blocks: check_pending_shard_blocks(spec, store, shard, shard_blocks_buffer) # Use temporary next state to get ShardTransition of shard block shard_transitions = get_shard_transitions(spec, state, shard_block_dict={shard: shard_blocks_buffer}) shard_transition = shard_transitions[shard] attestation = get_valid_on_time_attestation( spec, state, index=committee_index, shard_transition=shard_transition, signed=True, ) assert attestation.data.shard == shard beacon_block.body.attestations = [attestation] beacon_block.body.shard_transitions = shard_transitions # Clear buffer shard_blocks_buffer.clear() return beacon_block
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( spec, state, state.slot + 1 + spec.MIN_ATTESTATION_INCLUSION_DELAY) attestation_block.body.attestations.append(attestation) signed_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(spec, state, state.slot + spec.SLOTS_PER_EPOCH) signed_epoch_block = state_transition_and_sign_block( spec, state, epoch_block) yield 'blocks', [signed_attestation_block, signed_epoch_block] 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_ex_ante_sandwich_without_attestations(spec, state): """ Simple Sandwich test with boost and no attestations. Obejcts: Block A - slot N Block B (parent A) - slot N+1 Block C (parent A) - slot N+2 Block D (parent B) - slot N+3 Steps: Block A received at N — A is head Block C received at N+2 — C is head Block B received at N+2 — C is head (with boost) Block D received at N+3 — D is head (with boost) """ 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 # On receiving block A at slot `N` yield from _apply_base_block_a(spec, state, store, test_steps) state_a = state.copy() # Block B at slot `N + 1`, parent is A state_b = state_a.copy() block = build_empty_block(spec, state_a, slot=state_a.slot + 1) signed_block_b = state_transition_and_sign_block(spec, state_b, block) # Block C at slot `N + 2`, parent is A state_c = state_a.copy() block = build_empty_block(spec, state_c, slot=state_a.slot + 2) signed_block_c = state_transition_and_sign_block(spec, state_c, block) # Block D at slot `N + 3`, parent is B state_d = state_b.copy() block = build_empty_block(spec, state_d, slot=state_a.slot + 3) signed_block_d = state_transition_and_sign_block(spec, state_d, block) # Block C received at N+2 — C is head time = state_c.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block_c, test_steps) assert spec.get_head(store) == signed_block_c.message.hash_tree_root() # Block B received at N+2 — C is head, it has proposer score boost yield from add_block(spec, store, signed_block_b, test_steps) assert spec.get_head(store) == signed_block_c.message.hash_tree_root() # Block D received at N+3 - D is head, it has proposer score boost time = state_d.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block_d, test_steps) assert spec.get_head(store) == signed_block_d.message.hash_tree_root() yield 'steps', test_steps
def test_custody_slashing(spec, state): # NOTE: this test is only for full crosslink (minimal config), not for mainnet if not is_full_crosslink(spec, state): # skip return state = transition_to_valid_shard_slot(spec, state) # Build shard block shard = 0 committee_index = get_committee_index_of_shard(spec, state, state.slot, shard) # Create slashable shard block body validator_index = spec.get_beacon_committee(state, state.slot, committee_index)[0] custody_secret = get_custody_secret(spec, state, validator_index) slashable_body = get_custody_slashable_test_vector(spec, custody_secret, length=100, slashable=True) shard_block = build_shard_block(spec, state, shard, body=slashable_body, slot=state.slot, signed=True) shard_block_dict: Dict[spec.Shard, Sequence[spec.SignedShardBlock]] = { shard: [shard_block] } shard_transitions = get_shard_transitions(spec, state, shard_block_dict) attestation = get_valid_on_time_attestation( spec, state, index=committee_index, shard_transition=shard_transitions[shard], signed=True, ) block = build_empty_block(spec, state, slot=state.slot + 1) block.body.attestations = [attestation] block.body.shard_transitions = shard_transitions _, _, _ = run_beacon_block(spec, state, block) transition_to( spec, state, state.slot + spec.SLOTS_PER_EPOCH * (spec.EPOCHS_PER_CUSTODY_PERIOD - 1)) block = build_empty_block(spec, state, slot=state.slot + 1) custody_slashing = get_valid_custody_slashing(spec, state, attestation, shard_transitions[shard], custody_secret, slashable_body) block.body.custody_slashings = [custody_slashing] yield from run_beacon_block(spec, state, block)
def test_custody_slashing(spec, state): transition_to_valid_shard_slot(spec, state) # Build shard block shard = 0 committee_index = get_committee_index_of_shard(spec, state, state.slot, shard) # Create slashable shard block body validator_index = spec.get_beacon_committee(state, state.slot, committee_index)[0] custody_secret = spec.get_custody_secret( state, validator_index, privkeys[validator_index], spec.get_current_epoch(state), ) slashable_body = get_custody_slashable_test_vector(spec, custody_secret, length=100, slashable=True) shard_block = build_shard_block(spec, state, shard, body=slashable_body, slot=state.slot, signed=True) shard_block_dict: Dict[spec.Shard, Sequence[spec.SignedShardBlock]] = { shard: [shard_block] } shard_transitions = get_shard_transitions(spec, state, shard_block_dict) attestation = get_valid_on_time_attestation( spec, state, index=committee_index, shard_transition=shard_transitions[shard], signed=True, ) block = build_empty_block(spec, state, slot=state.slot + 1) block.body.attestations = [attestation] block.body.shard_transitions = shard_transitions _, _, _ = run_beacon_block(spec, state, block) transition_to( spec, state, state.slot + spec.SLOTS_PER_EPOCH * (spec.EPOCHS_PER_CUSTODY_PERIOD - 1)) block = build_empty_block(spec, state, slot=state.slot + 1) custody_slashing = get_valid_custody_slashing(spec, state, attestation, shard_transitions[shard], custody_secret, slashable_body) block.body.custody_slashings = [custody_slashing] yield from run_beacon_block(spec, state, block)
def test_attestation(spec, state): next_epoch(spec, state) yield 'pre', state attestation_block = build_empty_block( spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) index = 0 # if spec.fork == SHARDING: # TODO add shard data to block to vote on attestation = get_valid_attestation(spec, state, index=index, signed=True, on_time=True) if not is_post_altair(spec): pre_current_attestations_len = len(state.current_epoch_attestations) # Add to state via block transition attestation_block.body.attestations.append(attestation) signed_attestation_block = state_transition_and_sign_block( spec, state, attestation_block) if not is_post_altair(spec): 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) else: pre_current_epoch_participation_root = spec.hash_tree_root( state.current_epoch_participation) epoch_block = build_empty_block(spec, state, state.slot + spec.SLOTS_PER_EPOCH) signed_epoch_block = state_transition_and_sign_block( spec, state, epoch_block) yield 'blocks', [signed_attestation_block, signed_epoch_block] yield 'post', state if not is_post_altair(spec): assert len(state.current_epoch_attestations) == 0 assert spec.hash_tree_root( state.previous_epoch_attestations) == pre_current_attestations_root else: for index in range(len(state.validators)): assert state.current_epoch_participation[ index] == spec.ParticipationFlags(0b0000_0000) assert spec.hash_tree_root(state.previous_epoch_participation ) == pre_current_epoch_participation_root
def test_inactivity_scores_full_participation_leaking(spec, state): randomize_inactivity_scores(spec, state, rng=Random(5252)) assert len(set(state.inactivity_scores)) > 1 # Only set full participation for previous epoch to remain in leak set_full_participation_previous_epoch(spec, state) previous_inactivity_scores = state.inactivity_scores.copy() yield 'pre', state # Block transition to next epoch block = build_empty_block(spec, state, slot=state.slot + spec.SLOTS_PER_EPOCH) signed_block = state_transition_and_sign_block(spec, state, block) assert spec.is_in_inactivity_leak(state) yield 'blocks', [signed_block] yield 'post', state # Full particiaption during a leak so all scores should decrease by 1 for pre, post in zip(previous_inactivity_scores, state.inactivity_scores): assert post == pre - 1
def test_early_derived_secret_reveal(spec, state): transition_to_valid_shard_slot(spec, state) block = build_empty_block(spec, state, slot=state.slot + 1) early_derived_secret_reveal = get_valid_early_derived_secret_reveal(spec, state) block.body.early_derived_secret_reveals = [early_derived_secret_reveal] yield from run_beacon_block(spec, state, block)
def test_eth1_data_votes_no_consensus(spec, state): if spec.EPOCHS_PER_ETH1_VOTING_PERIOD > 2: return dump_skipping_message( "Skip test if config with longer `EPOCHS_PER_ETH1_VOTING_PERIOD` for saving time." " Minimal config suffice to cover the target-of-test.") voting_period_slots = spec.EPOCHS_PER_ETH1_VOTING_PERIOD * spec.SLOTS_PER_EPOCH pre_eth1_hash = state.eth1_data.block_hash offset_block = build_empty_block(spec, state, slot=voting_period_slots - 1) state_transition_and_sign_block(spec, state, offset_block) yield 'pre', state a = b'\xaa' * 32 b = b'\xbb' * 32 blocks = [] for i in range(0, voting_period_slots): block = build_empty_block_for_next_slot(spec, state) # wait for precisely 50% for A, then start voting B for other 50% block.body.eth1_data.block_hash = b if i * 2 >= voting_period_slots else a signed_block = state_transition_and_sign_block(spec, state, block) blocks.append(signed_block) assert len(state.eth1_data_votes) == voting_period_slots assert state.eth1_data.block_hash == pre_eth1_hash yield 'blocks', blocks yield 'post', state
def test_voluntary_exit(spec, state): validator_index = spec.get_active_validator_indices( state, spec.get_current_epoch(state))[-1] # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit state.slot += spec.config.SHARD_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH signed_exits = prepare_signed_exits(spec, state, [validator_index]) yield 'pre', state # Add to state via block transition initiate_exit_block = build_empty_block_for_next_slot(spec, state) initiate_exit_block.body.voluntary_exits = signed_exits signed_initiate_exit_block = state_transition_and_sign_block( spec, state, initiate_exit_block) assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH # Process within epoch transition exit_block = build_empty_block(spec, state, state.slot + spec.SLOTS_PER_EPOCH) signed_exit_block = state_transition_and_sign_block( spec, state, exit_block) yield 'blocks', [signed_initiate_exit_block, signed_exit_block] yield 'post', state assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
def test_eth1_data_votes_no_consensus(spec, state): voting_period_slots = spec.EPOCHS_PER_ETH1_VOTING_PERIOD * spec.SLOTS_PER_EPOCH pre_eth1_hash = state.eth1_data.block_hash offset_block = build_empty_block(spec, state, slot=voting_period_slots - 1) state_transition_and_sign_block(spec, state, offset_block) yield 'pre', state a = b'\xaa' * 32 b = b'\xbb' * 32 blocks = [] for i in range(0, voting_period_slots): block = build_empty_block_for_next_slot(spec, state) # wait for precisely 50% for A, then start voting B for other 50% block.body.eth1_data.block_hash = b if i * 2 >= voting_period_slots else a signed_block = state_transition_and_sign_block(spec, state, block) blocks.append(signed_block) assert len(state.eth1_data_votes) == voting_period_slots assert state.eth1_data.block_hash == pre_eth1_hash yield 'blocks', blocks yield 'post', state
def test_eth1_data_votes_no_consensus(spec, state): # Don't run when it will take very, very long to simulate. Minimal configuration suffices. if spec.SLOTS_PER_ETH1_VOTING_PERIOD > 16: return pre_eth1_hash = state.eth1_data.block_hash offset_block = build_empty_block(spec, state, slot=spec.SLOTS_PER_ETH1_VOTING_PERIOD - 1) state_transition_and_sign_block(spec, state, offset_block) yield 'pre', state a = b'\xaa' * 32 b = b'\xbb' * 32 blocks = [] for i in range(0, spec.SLOTS_PER_ETH1_VOTING_PERIOD): block = build_empty_block_for_next_slot(spec, state) # wait for precisely 50% for A, then start voting B for other 50% block.body.eth1_data.block_hash = b if i * 2 >= spec.SLOTS_PER_ETH1_VOTING_PERIOD else a signed_block = state_transition_and_sign_block(spec, state, block) blocks.append(signed_block) assert len(state.eth1_data_votes) == spec.SLOTS_PER_ETH1_VOTING_PERIOD assert state.eth1_data.block_hash == pre_eth1_hash yield 'blocks', blocks yield 'post', state
def test_with_shard_transition_with_custody_challenge_and_response(spec, state): transition_to_valid_shard_slot(spec, state) # build shard block shard = 0 committee_index = get_committee_index_of_shard(spec, state, state.slot, shard) body = get_sample_shard_block_body(spec) shard_block = build_shard_block(spec, state, shard, body=body, slot=state.slot, signed=True) shard_block_dict: Dict[spec.Shard, Sequence[spec.SignedShardBlock]] = {shard: [shard_block]} shard_transitions = get_shard_transitions(spec, state, shard_block_dict) attestation = get_valid_on_time_attestation( spec, state, index=committee_index, shard_transition=shard_transitions[shard], signed=True, ) block = build_empty_block(spec, state, slot=state.slot + 1) block.body.attestations = [attestation] block.body.shard_transitions = shard_transitions # CustodyChunkChallenge operation challenge = get_valid_chunk_challenge(spec, state, attestation, shard_transitions[shard]) block.body.chunk_challenges = [challenge] # CustodyChunkResponse operation chunk_challenge_index = state.custody_chunk_challenge_index custody_response = get_valid_custody_chunk_response( spec, state, challenge, chunk_challenge_index, block_length_or_custody_data=body) block.body.chunk_challenge_responses = [custody_response] yield from run_beacon_block(spec, state, block)
def test_custody_key_reveal(spec, state): transition_to_valid_shard_slot(spec, state) transition_to(spec, state, state.slot + spec.EPOCHS_PER_CUSTODY_PERIOD * spec.SLOTS_PER_EPOCH) block = build_empty_block(spec, state, slot=state.slot + 1) custody_key_reveal = get_valid_custody_key_reveal(spec, state) block.body.custody_key_reveals = [custody_key_reveal] yield from run_beacon_block(spec, state, block)
def test_same_slot_block_transition(spec, state): # Same slot on top of pre-state, but move out of slot 0 first. spec.process_slots(state, state.slot + 1) block = build_empty_block(spec, state, slot=state.slot) yield 'pre', state signed_block = state_transition_and_sign_block(spec, state, block) yield 'blocks', [signed_block] yield 'post', state
def test_prev_slot_block_transition(spec, state): # Go to clean slot spec.process_slots(state, state.slot + 1) # Make a block for it block = build_empty_block(spec, state, slot=state.slot, signed=True) # Transition to next slot, above block will not be invalid on top of new state. spec.process_slots(state, state.slot + 1) yield 'pre', state expect_assertion_error( lambda: state_transition_and_sign_block(spec, state, block)) yield 'blocks', [block] yield 'post', None
def test_compute_new_state_root(spec, state): pre_state = state.copy() post_state = state.copy() block = build_empty_block(spec, state, state.slot + 1) state_root = spec.compute_new_state_root(state, block) assert state_root != pre_state.hash_tree_root() assert state == pre_state # dumb verification spec.process_slots(post_state, block.slot) spec.process_block(post_state, block) assert state_root == post_state.hash_tree_root()
def run_beacon_block_with_shard_blocks(spec, state, shard_blocks, target_len_offset_slot, committee_index, valid=True): shard_transitions = build_shard_transitions_till_slot( spec, state, shard_blocks, on_time_slot=state.slot + target_len_offset_slot) attestations = [ build_attestation_with_shard_transition( spec, state, on_time_slot=state.slot + target_len_offset_slot, index=committee_index, shard_transition=shard_transitions[shard], ) for shard in shard_blocks.keys() ] # Propose beacon block at slot `x + 1` beacon_block = build_empty_block(spec, state, slot=state.slot + target_len_offset_slot) beacon_block.body.attestations = attestations beacon_block.body.shard_transitions = shard_transitions pre_shard_states = state.shard_states.copy() yield 'pre', state.copy() yield 'block', beacon_block state_transition_and_sign_block(spec, state, beacon_block) if valid: yield 'post', state else: yield 'post', None return for shard in range(spec.get_active_shard_count(state)): post_shard_state = state.shard_states[shard] if shard in shard_blocks: # Shard state has been changed to state_transition result assert post_shard_state == shard_transitions[shard].shard_states[ len(shard_transitions[shard].shard_states) - 1] assert beacon_block.slot == shard_transitions[shard].shard_states[ 0].slot + target_len_offset_slot assert post_shard_state.slot == state.slot - 1 if len(shard_blocks[shard]) == 0: # `latest_block_root` is the same assert post_shard_state.latest_block_root == pre_shard_states[ shard].latest_block_root
def test_empty_epoch_transition_large_validator_set(spec, state): pre_slot = state.slot yield 'pre', state block = build_empty_block(spec, state, state.slot + spec.SLOTS_PER_EPOCH) signed_block = state_transition_and_sign_block(spec, state, block) yield 'blocks', [signed_block] yield 'post', state assert state.slot == block.slot for slot in range(pre_slot, state.slot): assert spec.get_block_root_at_slot(state, slot) == block.parent_root
def test_get_block_signature(spec, state): privkey = privkeys[0] pubkey = pubkeys[0] block = build_empty_block(spec, state) domain = spec.get_domain(state, spec.DOMAIN_BEACON_PROPOSER, spec.compute_epoch_at_slot(block.slot)) run_get_signature_test( spec=spec, state=state, obj=block, domain=domain, get_signature_fn=spec.get_block_signature, privkey=privkey, pubkey=pubkey, )
def run_beacon_block_with_shard_blocks(spec, state, target_len_offset_slot, committee_index, shard, valid=True): transition_to(spec, state, state.slot + target_len_offset_slot) body = get_sample_shard_block_body(spec, is_max=True) shard_block = build_shard_block(spec, state, shard, body=body, slot=state.slot, signed=True) shard_block_dict: Dict[spec.Shard, Sequence[spec.SignedShardBlock]] = {shard: [shard_block]} shard_transitions = get_shard_transitions(spec, state, shard_block_dict) attestations = [ get_valid_on_time_attestation( spec, state, index=committee_index, shard_transition=shard_transitions[shard], signed=True, ) for shard in shard_block_dict.keys() ] beacon_block = build_empty_block(spec, state, slot=state.slot + 1) beacon_block.body.attestations = attestations beacon_block.body.shard_transitions = shard_transitions pre_gasprice = state.shard_states[shard].gasprice pre_shard_states = state.shard_states.copy() yield 'pre', state.copy() if not valid: state_transition_and_sign_block(spec, state, beacon_block, expect_fail=True) yield 'block', beacon_block yield 'post', None return signed_beacon_block = state_transition_and_sign_block(spec, state, beacon_block) yield 'block', signed_beacon_block yield 'post', state for shard in range(spec.get_active_shard_count(state)): post_shard_state = state.shard_states[shard] if shard in shard_block_dict: # Shard state has been changed to state_transition result assert post_shard_state == shard_transitions[shard].shard_states[ len(shard_transitions[shard].shard_states) - 1 ] assert post_shard_state.slot == state.slot - 1 if len((shard_block_dict[shard])) == 0: # `latest_block_root` is the same assert post_shard_state.latest_block_root == pre_shard_states[shard].latest_block_root if target_len_offset_slot == 1 and len(shard_block_dict[shard]) > 0: assert post_shard_state.gasprice > pre_gasprice
def test_attestation(spec, state): next_epoch(spec, state) yield 'pre', state attestation_block = build_empty_block(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) index = 0 if spec.fork == PHASE1: shard = spec.compute_shard_from_committee_index(state, index, state.slot) shard_transition = get_shard_transition_of_committee(spec, state, index) attestation_block.body.shard_transitions[shard] = shard_transition else: shard_transition = None attestation = get_valid_attestation( spec, state, shard_transition=shard_transition, index=index, signed=True, on_time=True ) # Add to state via block transition pre_current_attestations_len = len(state.current_epoch_attestations) attestation_block.body.attestations.append(attestation) signed_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(spec, state, state.slot + spec.SLOTS_PER_EPOCH) signed_epoch_block = state_transition_and_sign_block(spec, state, epoch_block) yield 'blocks', [signed_attestation_block, signed_epoch_block] 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_skipped_slots(spec, state): pre_slot = state.slot yield 'pre', state block = build_empty_block(spec, state, state.slot + 4) signed_block = state_transition_and_sign_block(spec, state, block) yield 'blocks', [signed_block] yield 'post', state assert state.slot == block.slot assert spec.get_randao_mix(state, spec.get_current_epoch(state)) != spec.Bytes32() for slot in range(pre_slot, state.slot): assert spec.get_block_root_at_slot(state, slot) == block.parent_root
def _state_transition_and_sign_block_at_slot(spec, state): """ Cribbed from ``transition_unsigned_block`` helper where the early parts of the state transition have already been applied to ``state``. Used to produce a block during an irregular state transition. """ block = build_empty_block(spec, state) assert state.latest_block_header.slot < block.slot assert state.slot == block.slot spec.process_block(state, block) block.state_root = state.hash_tree_root() return sign_block(spec, state, block)
def apply_shard_and_beacon(spec, state, store, shard_store, shard_blocks_buffer): store.time = store.time + spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH shard = shard_store.shard committee_index = get_committee_index_of_shard(spec, state, state.slot, shard) has_shard_committee = committee_index is not None # has committee of `shard` at this slot beacon_block = build_empty_block(spec, state, slot=state.slot + 1) # If next slot has committee of `shard`, add `shard_transtion` to the proposing beacon block if has_shard_committee and len(shard_blocks_buffer) > 0: # Sanity check `get_pending_shard_blocks` function check_pending_shard_blocks(spec, store, shard_store, shard_blocks_buffer) # Use temporary next state to get ShardTransition of shard block shard_transitions = get_shard_transitions( spec, state, shard_block_dict={shard: shard_blocks_buffer}, ) shard_transition = shard_transitions[shard] attestation = get_valid_on_time_attestation( spec, state, index=committee_index, shard_transition=shard_transition, signed=False, ) assert attestation.data.shard == shard beacon_block.body.attestations = [attestation] beacon_block.body.shard_transitions = shard_transitions # Clear buffer shard_blocks_buffer.clear() signed_beacon_block = state_transition_and_sign_block( spec, state, beacon_block) # transition! add_block_to_store(spec, store, signed_beacon_block) assert spec.get_head(store) == beacon_block.hash_tree_root() # On shard block at transitioned `state.slot` if is_in_offset_sets(spec, state, shard): # The created shard block would be appended to `shard_blocks_buffer` apply_shard_block(spec, store, shard_store, state, shard_blocks_buffer) return has_shard_committee
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_prev_slot_block_transition(spec, state): # Go to clean slot spec.process_slots(state, state.slot + 1) # Make a block for it block = build_empty_block(spec, state, slot=state.slot) proposer_index = spec.get_beacon_proposer_index(state) # Transition to next slot, above block will not be invalid on top of new state. spec.process_slots(state, state.slot + 1) yield 'pre', state # State is beyond block slot, but the block can still be realistic when invalid. # Try the transition, and update the state root to where it is halted. Then sign with the supposed proposer. expect_assertion_error(lambda: transition_unsigned_block(spec, state, block)) block.state_root = state.hash_tree_root() signed_block = sign_block(spec, state, block, proposer_index=proposer_index) yield 'blocks', [signed_block] yield 'post', None
def test_inactivity_scores(spec, state): for _ in range(spec.MIN_EPOCHS_TO_INACTIVITY_PENALTY + 2): next_epoch_via_block(spec, state) assert spec.is_in_inactivity_leak(state) previous_inactivity_scores = state.inactivity_scores.copy() yield 'pre', state # Block transition to next epoch block = build_empty_block(spec, state, slot=state.slot + spec.SLOTS_PER_EPOCH) signed_block = state_transition_and_sign_block(spec, state, block) yield 'blocks', [signed_block] yield 'post', state for pre, post in zip(previous_inactivity_scores, state.inactivity_scores): assert post == pre + spec.INACTIVITY_SCORE_BIAS
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_eth1_data_votes_consensus(spec, state): # Don't run when it will take very, very long to simulate. Minimal configuration suffices. if spec.SLOTS_PER_ETH1_VOTING_PERIOD > 16: return offset_block = build_empty_block(spec, state, slot=spec.SLOTS_PER_ETH1_VOTING_PERIOD - 1) sign_block(spec, state, offset_block) state_transition_and_sign_block(spec, state, offset_block) yield 'pre', state a = b'\xaa' * 32 b = b'\xbb' * 32 c = b'\xcc' * 32 blocks = [] for i in range(0, spec.SLOTS_PER_ETH1_VOTING_PERIOD): block = build_empty_block_for_next_slot(spec, state) # wait for over 50% for A, then start voting B block.body.eth1_data.block_hash = b if i * 2 > spec.SLOTS_PER_ETH1_VOTING_PERIOD else a sign_block(spec, state, block) state_transition_and_sign_block(spec, state, block) blocks.append(block) assert len(state.eth1_data_votes) == spec.SLOTS_PER_ETH1_VOTING_PERIOD assert state.eth1_data.block_hash == a # transition to next eth1 voting period block = build_empty_block_for_next_slot(spec, state) block.body.eth1_data.block_hash = c sign_block(spec, state, block) state_transition_and_sign_block(spec, state, block) blocks.append(block) yield 'blocks', blocks yield 'post', state assert state.eth1_data.block_hash == a assert state.slot % spec.SLOTS_PER_ETH1_VOTING_PERIOD == 0 assert len(state.eth1_data_votes) == 1 assert state.eth1_data_votes[0].block_hash == c