def test_on_time_success(spec, state): attestation = get_valid_on_time_attestation(spec, state, signed=True) transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) yield from run_attestation_processing(spec, state, attestation)
def test_challenge_empty_element_replaced(spec, state): transition_to(spec, state, state.slot + 1) shard = 0 offset_slots = spec.get_offset_slots(state, shard) shard_transition = get_sample_shard_transition( spec, state.slot, [2**15 // 3] * len(offset_slots)) attestation = get_valid_on_time_attestation( spec, state, index=shard, signed=True, shard_transition=shard_transition) transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) _, _, _ = run_attestation_processing(spec, state, attestation) transition_to( spec, state, state.slot + spec.SLOTS_PER_EPOCH * spec.EPOCHS_PER_CUSTODY_PERIOD) challenge = get_valid_chunk_challenge(spec, state, attestation, shard_transition) state.custody_chunk_challenge_records.append( spec.CustodyChunkChallengeRecord()) yield from run_chunk_challenge_processing(spec, state, challenge)
def test_validator_slashed_after_chunk_challenge(spec, state): transition_to_valid_shard_slot(spec, state) transition_to(spec, state, state.slot + 1) # Make len(offset_slots) == 1 shard = 0 offset_slots = spec.get_offset_slots(state, shard) shard_transition = get_sample_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots)) attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition=shard_transition) transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) _, _, _ = run_attestation_processing(spec, state, attestation) validator_index = spec.get_beacon_committee( state, attestation.data.slot, attestation.data.index )[0] challenge = get_valid_chunk_challenge(spec, state, attestation, shard_transition) _, _, _ = run_chunk_challenge_processing(spec, state, challenge) assert state.validators[validator_index].slashed == 0 transition_to(spec, state, state.slot + spec.MAX_CHUNK_CHALLENGE_DELAY * spec.SLOTS_PER_EPOCH) state.validators[validator_index].slashed = 0 yield from run_process_challenge_deadlines(spec, state) assert state.validators[validator_index].slashed == 1
def run_standard_custody_slashing_test(spec, state, shard_lateness=None, shard=None, validator_index=None, block_lengths=None, slashing_message_data=None, correct=True, valid=True): if shard_lateness is None: shard_lateness = spec.SLOTS_PER_EPOCH transition_to(spec, state, state.slot + shard_lateness) if shard is None: shard = 0 if validator_index is None: validator_index = spec.get_beacon_committee(state, state.slot, shard)[0] offset_slots = spec.get_offset_slots(state, shard) if block_lengths is None: block_lengths = [2**15 // 3] * len(offset_slots) custody_secret = get_custody_secret(spec, state, validator_index) shard_transition, slashable_test_vector = get_custody_slashable_shard_transition( spec, state.slot, block_lengths, custody_secret, slashable=correct, ) attestation = get_valid_on_time_attestation( spec, state, index=shard, signed=True, shard_transition=shard_transition) transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) _, _, _ = run_attestation_processing(spec, state, attestation) transition_to( spec, state, state.slot + spec.SLOTS_PER_EPOCH * (spec.EPOCHS_PER_CUSTODY_PERIOD - 1)) slashing = get_valid_custody_slashing(spec, state, attestation, shard_transition, custody_secret, slashable_test_vector) if slashing_message_data is not None: slashing.message.data = slashing_message_data yield from run_custody_slashing_processing(spec, state, slashing, valid=valid, correct=correct)
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 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_challenge_appended(spec, state): transition_to_valid_shard_slot(spec, state) transition_to(spec, state, state.slot + 1) # Make len(offset_slots) == 1 shard = 0 offset_slots = spec.get_offset_slots(state, shard) shard_transition = get_sample_shard_transition( spec, state.slot, [2**15 // 3] * len(offset_slots)) attestation = get_valid_on_time_attestation( spec, state, index=shard, signed=True, shard_transition=shard_transition) transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) _, _, _ = run_attestation_processing(spec, state, attestation) transition_to( spec, state, state.slot + spec.SLOTS_PER_EPOCH * spec.EPOCHS_PER_CUSTODY_PERIOD) challenge = get_valid_chunk_challenge(spec, state, attestation, shard_transition) yield from run_chunk_challenge_processing(spec, state, challenge)
def test_custody_response_many_epochs(spec, state): transition_to_valid_shard_slot(spec, state) transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * 20) shard = 0 offset_slots = spec.get_offset_slots(state, shard) shard_transition = get_sample_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots)) attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition=shard_transition) transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) _, _, _ = run_attestation_processing(spec, state, attestation) transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * (spec.EPOCHS_PER_CUSTODY_PERIOD - 1)) challenge = get_valid_chunk_challenge(spec, state, attestation, shard_transition) _, _, _ = run_chunk_challenge_processing(spec, state, challenge) chunk_challenge_index = state.custody_chunk_challenge_index - 1 custody_response = get_valid_custody_chunk_response( spec, state, challenge, chunk_challenge_index, block_length_or_custody_data=2**15 // 3) yield from run_custody_chunk_response_processing(spec, state, custody_response)
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_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_validator_withdrawal_resume_after_chunk_challenge_response(spec, state): transition_to_valid_shard_slot(spec, state) transition_to(spec, state, state.slot + 1) # Make len(offset_slots) == 1 shard = 0 offset_slots = spec.get_offset_slots(state, shard) shard_transition = get_sample_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots)) attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition=shard_transition) transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) _, _, _ = run_attestation_processing(spec, state, attestation) validator_index = spec.get_beacon_committee( state, attestation.data.slot, attestation.data.index )[0] spec.initiate_validator_exit(state, validator_index) assert state.validators[validator_index].withdrawable_epoch < spec.FAR_FUTURE_EPOCH next_epoch_via_block(spec, state) assert state.validators[validator_index].withdrawable_epoch == spec.FAR_FUTURE_EPOCH while spec.get_current_epoch(state) < state.validators[validator_index].exit_epoch: next_epoch_via_block(spec, state) while (state.validators[validator_index].next_custody_secret_to_reveal <= spec.get_custody_period_for_validator( validator_index, state.validators[validator_index].exit_epoch - 1)): custody_key_reveal = get_valid_custody_key_reveal(spec, state, validator_index=validator_index) _, _, _ = run_custody_key_reveal_processing(spec, state, custody_key_reveal) next_epoch_via_block(spec, state) challenge = get_valid_chunk_challenge(spec, state, attestation, shard_transition) _, _, _ = run_chunk_challenge_processing(spec, state, challenge) next_epoch_via_block(spec, state) assert state.validators[validator_index].withdrawable_epoch == spec.FAR_FUTURE_EPOCH chunk_challenge_index = state.custody_chunk_challenge_index - 1 custody_response = get_valid_custody_chunk_response( spec, state, challenge, chunk_challenge_index, block_length_or_custody_data=2**15 // 3) _, _, _ = run_custody_chunk_response_processing(spec, state, custody_response) yield from run_process_custody_final_updates(spec, state) assert state.validators[validator_index].withdrawable_epoch < spec.FAR_FUTURE_EPOCH
def create_attestation_for_shard_blocks(spec, beacon_parent_state, shard, committee_index, blocks, filter_participant_set=None): shard_transition = spec.get_shard_transition(beacon_parent_state, shard, blocks) attestation = get_valid_on_time_attestation( spec, beacon_parent_state, index=committee_index, shard_transition=shard_transition, signed=True, ) return attestation
def get_attestations_and_shard_transitions(spec, state, shard_block_dict): shard_transitions = get_shard_transitions(spec, state, shard_block_dict) attestations = [ get_valid_on_time_attestation( spec, state, index=get_committee_index_of_shard(spec, state, state.slot, shard), shard_transition=shard_transition, signed=True, ) for shard, shard_transition in enumerate(shard_transitions) if shard_transition != spec.ShardTransition() ] return attestations, shard_transitions
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_off_chain_attestation(spec, state): transition_to_valid_shard_slot(spec, state) transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH) shard = 0 offset_slots = spec.get_offset_slots(state, shard) shard_transition = get_sample_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots)) attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, shard_transition=shard_transition) transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * (spec.EPOCHS_PER_CUSTODY_PERIOD - 1)) challenge = get_valid_chunk_challenge(spec, state, attestation, shard_transition) yield from run_chunk_challenge_processing(spec, state, challenge)
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 build_attestation_with_shard_transition(spec, state, index, on_time_slot, shard_transition=None): temp_state = state.copy() transition_to(spec, temp_state, on_time_slot - 1) attestation = get_valid_on_time_attestation( spec, temp_state, index=index, shard_transition=shard_transition, signed=True, ) assert attestation.data.slot == temp_state.slot if shard_transition is not None: assert attestation.data.shard_transition_root == shard_transition.hash_tree_root( ) return attestation
def test_late_with_custody_bits_blocks(spec, state): attestation = get_valid_on_time_attestation(spec, state, signed=True) transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY + 1) yield from run_attestation_processing(spec, state, attestation, False)