def test_attester_slashing(spec, state): # copy for later balance lookups. pre_state = state.copy() attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) slashed_indices = get_indexed_attestation_participants( spec, attester_slashing.attestation_1) assert not any(state.validators[i].slashed for i in slashed_indices) yield 'pre', state # # Add to state via block transition # block = build_empty_block_for_next_slot(spec, state) block.body.attester_slashings.append(attester_slashing) signed_block = state_transition_and_sign_block(spec, state, block) yield 'blocks', [signed_block] yield 'post', state check_attester_slashing_effect(spec, pre_state, state, slashed_indices)
def test_same_data(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) attester_slashing.attestation_1.data = attester_slashing.attestation_2.data sign_indexed_attestation(spec, state, attester_slashing.attestation_1) yield from run_attester_slashing_processing(spec, state, attester_slashing, False)
def test_no_double_or_surround(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) attester_slashing.attestation_1.data.target.epoch += 1 sign_indexed_attestation(spec, state, attester_slashing.attestation_1) yield from run_attester_slashing_processing(spec, state, attester_slashing, False)
def test_success_already_exited_recent(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) slashed_indices = attester_slashing.attestation_1.attesting_indices for index in slashed_indices: spec.initiate_validator_exit(state, index) yield from run_attester_slashing_processing(spec, state, attester_slashing)
def test_duplicate_attester_slashing(spec, state): if spec.MAX_ATTESTER_SLASHINGS < 2: return dump_skipping_message( "Skip test if config cannot handle multiple AttesterSlashings per block" ) attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) attester_slashings = [attester_slashing, attester_slashing.copy()] slashed_indices = get_indexed_attestation_participants( spec, attester_slashing.attestation_1) assert not any(state.validators[i].slashed for i in slashed_indices) yield 'pre', state # # Add to state via block transition # block = build_empty_block_for_next_slot(spec, state) block.body.attester_slashings = attester_slashings signed_block = state_transition_and_sign_block(spec, state, block, expect_fail=True) yield 'blocks', [signed_block] yield 'post', None
def test_attester_slashing(spec, state): # copy for later balance lookups. pre_state = deepcopy(state) attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) validator_index = get_indexed_attestation_participants(spec, attester_slashing.attestation_1)[0] assert not state.validators[validator_index].slashed yield 'pre', state # # Add to state via block transition # block = build_empty_block_for_next_slot(spec, state) block.body.attester_slashings.append(attester_slashing) signed_block = state_transition_and_sign_block(spec, state, block) yield 'blocks', [signed_block] yield 'post', state slashed_validator = state.validators[validator_index] assert slashed_validator.slashed assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH # lost whistleblower reward assert get_balance(state, validator_index) < get_balance(pre_state, validator_index) proposer_index = spec.get_beacon_proposer_index(state) # gained whistleblower reward assert ( get_balance(state, proposer_index) > get_balance(pre_state, proposer_index) )
def test_invalid_sig_1_and_2(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=False) yield from run_attester_slashing_processing(spec, state, attester_slashing, False)
def test_success_double(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) yield from run_attester_slashing_processing(spec, state, attester_slashing)
def test_success_already_exited_long_ago(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) slashed_indices = attester_slashing.attestation_1.attesting_indices for index in slashed_indices: spec.initiate_validator_exit(state, index) state.validators[index].withdrawable_epoch = spec.get_current_epoch(state) + 2 yield from run_attester_slashing_processing(spec, state, attester_slashing)
def test_participants_already_slashed(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) # set all indices to slashed validator_indices = attester_slashing.attestation_1.attesting_indices for index in validator_indices: state.validators[index].slashed = True yield from run_attester_slashing_processing(spec, state, attester_slashing, False)
def test_unsorted_att_2(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=False) indices = attester_slashing.attestation_2.attesting_indices assert len(indices) >= 3 indices[1], indices[2] = indices[2], indices[1] # unsort second and third index sign_indexed_attestation(spec, state, attester_slashing.attestation_2) yield from run_attester_slashing_processing(spec, state, attester_slashing, False)
def test_att2_duplicate_index_double_signed(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=False) indices = attester_slashing.attestation_2.attesting_indices indices.pop(1) # remove an index, make room for the additional duplicate index. indices.append(indices[2]) # add one of the indices a second time attester_slashing.attestation_2.attesting_indices = sorted(indices) sign_indexed_attestation(spec, state, attester_slashing.attestation_2) # will have one attester signing it double yield from run_attester_slashing_processing(spec, state, attester_slashing, False)
def test_custody_bit_0_and_1(state): attester_slashing = get_valid_attester_slashing(state, signed_1=False, signed_2=True) attester_slashing.attestation_1.custody_bit_1_indices = ( attester_slashing.attestation_1.custody_bit_0_indices) sign_indexed_attestation(state, attester_slashing.attestation_1) yield from run_attester_slashing_processing(state, attester_slashing, False)
def test_att1_empty_indices(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) attester_slashing.attestation_1.attesting_indices = [] attester_slashing.attestation_1.signature = spec.bls.Z2_SIGNATURE yield from run_attester_slashing_processing(spec, state, attester_slashing, False)
def test_att1_bad_extra_index(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) indices = get_indexed_attestation_participants(spec, attester_slashing.attestation_1) options = list(set(range(len(state.validators))) - set(indices)) indices.append(options[len(options) // 2]) # add random index, not previously in attestation. attester_slashing.attestation_1.attesting_indices = sorted(indices) # Do not sign the modified attestation (it's ok to slash if attester signed, not if they did not), # see if the bad extra index is spotted, and slashing is aborted. yield from run_attester_slashing_processing(spec, state, attester_slashing, False)
def test_att2_bad_replaced_index(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) indices = attester_slashing.attestation_2.attesting_indices options = list(set(range(len(state.validators))) - set(indices)) indices[3] = options[len(options) // 2] # replace with random index, not previously in attestation. attester_slashing.attestation_2.attesting_indices = sorted(indices) # Do not sign the modified attestation (it's ok to slash if attester signed, not if they did not), # see if the bad replaced index is spotted, and slashing is aborted. yield from run_attester_slashing_processing(spec, state, attester_slashing, False)
def test_att2_empty_indices(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=False) attester_slashing.attestation_2.attesting_indices = [] attester_slashing.attestation_2.signature = spec.bls.G2_POINT_AT_INFINITY yield from run_attester_slashing_processing(spec, state, attester_slashing, False)
def test_success_with_effective_balance_disparity(spec, state): # Jitter balances to be different from effective balances for i in range(len(state.balances)): pre = int(state.balances[i]) state.balances[i] += random.randrange(max(pre - 5000, 0), pre + 5000) attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) yield from run_attester_slashing_processing(spec, state, attester_slashing)
def test_same_data(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) indexed_att_1 = attester_slashing.attestation_1 att_2_data = get_attestation_2_data(spec, attester_slashing) if spec.fork == 'phase1': indexed_att_1.attestation.data = att_2_data else: indexed_att_1.data = att_2_data sign_indexed_attestation(spec, state, attester_slashing.attestation_1) yield from run_attester_slashing_processing(spec, state, attester_slashing, False)
def test_participants_already_slashed(state): attester_slashing = get_valid_attester_slashing(state, signed_1=True, signed_2=True) # set all indices to slashed attestation_1 = attester_slashing.attestation_1 validator_indices = attestation_1.custody_bit_0_indices + attestation_1.custody_bit_1_indices for index in validator_indices: state.validator_registry[index].slashed = True yield from run_attester_slashing_processing(state, attester_slashing, False)
def test_att2_high_index(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True) indices = get_indexed_attestation_participants( spec, attester_slashing.attestation_2) indices.append(spec.ValidatorIndex(len(state.validators))) # off by 1 attester_slashing.attestation_2.attesting_indices = indices yield from run_attester_slashing_processing(spec, state, attester_slashing, False)
def test_success_attestation_from_future(spec, state): # Transition state to future to enable generation of a "future" attestation future_state = state.copy() next_epoch_via_block(spec, future_state) # Generate slashing using the future state attester_slashing = get_valid_attester_slashing( spec, future_state, slot=state.slot + 5, # Slot is in the future wrt `state` signed_1=True, signed_2=True) yield from run_attester_slashing_processing(spec, state, attester_slashing)
def test_att2_duplicate_index_normal_signed(spec, state): attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=False) indices = attester_slashing.attestation_2.attesting_indices indices.pop(2) # remove an index, make room for the additional duplicate index. attester_slashing.attestation_2.attesting_indices = sorted(indices) # sign it, the signature will be valid for a single occurence. If the transition accidentally ignores the duplicate. sign_indexed_attestation(spec, state, attester_slashing.attestation_2) indices.append(indices[1]) # add one of the indices a second time attester_slashing.attestation_2.attesting_indices = sorted(indices) # it will just appear normal, unless the double index is spotted yield from run_attester_slashing_processing(spec, state, attester_slashing, False)
def test_success_surround(spec, state): next_epoch(spec, state) apply_empty_block(spec, state) state.current_justified_checkpoint.epoch += 1 attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) attestation_1 = attester_slashing.attestation_1 attestation_2 = attester_slashing.attestation_2 # set attestion1 to surround attestation 2 attestation_1.data.source.epoch = attestation_2.data.source.epoch - 1 attestation_1.data.target.epoch = attestation_2.data.target.epoch + 1 sign_indexed_attestation(spec, state, attester_slashing.attestation_1) yield from run_attester_slashing_processing(spec, state, attester_slashing)