diff --git a/tests/core/pyspec/eth2spec/test/helpers/custody.py b/tests/core/pyspec/eth2spec/test/helpers/custody.py index 898cf7731..edd7ac19f 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/custody.py +++ b/tests/core/pyspec/eth2spec/test/helpers/custody.py @@ -59,7 +59,7 @@ def bitlist_from_int(max_len, num_bits, n): return Bitlist[max_len](*[(n >> i) & 0b1 for i in range(num_bits)]) -def get_valid_custody_slashing(spec, state, attestation, shard_transition, invalid_custody_bit=False): +def get_valid_custody_slashing(spec, state, attestation, shard_transition, custody_secret, data, data_index=0): beacon_committee = spec.get_beacon_committee( state, attestation.data.slot, @@ -68,21 +68,10 @@ def get_valid_custody_slashing(spec, state, attestation, shard_transition, inval malefactor_index = beacon_committee[0] whistleblower_index = beacon_committee[-1] - epoch = spec.get_randao_epoch_for_custody_period(attestation.data.target.epoch, - malefactor_index) - - # Generate the responder key - domain = spec.get_domain(state, spec.DOMAIN_RANDAO, epoch) - signing_root = spec.compute_signing_root(spec.Epoch(epoch), domain) - malefactor_key = bls.Sign(privkeys[malefactor_index], signing_root) - data_index = 0 - data = ByteList[spec.MAX_SHARD_BLOCK_SIZE]( - get_custody_test_vector(shard_transition.shard_block_lengths[data_index])) - slashing = spec.CustodySlashing( data_index=data_index, malefactor_index=malefactor_index, - malefactor_secret=malefactor_key, + malefactor_secret=custody_secret, whistleblower_index=whistleblower_index, shard_transition=shard_transition, attestation=attestation, @@ -165,9 +154,9 @@ def get_valid_custody_chunk_response(spec, state, chunk_challenge, block_length, ) -def get_custody_test_vector(bytelength): +def get_custody_test_vector(bytelength, offset=0): ints = bytelength // 4 + 1 - return (b"".join(i.to_bytes(4, "little") for i in range(ints)))[:bytelength] + return (b"".join((i + offset).to_bytes(4, "little") for i in range(ints)))[:bytelength] def get_shard_transition(spec, start_slot, block_lengths): @@ -181,3 +170,30 @@ def get_shard_transition(spec, start_slot, block_lengths): proposer_signature_aggregate=spec.BLSSignature(), ) return shard_transition + + +def get_custody_secret(spec, state, validator_index, epoch=None): + period = spec.get_custody_period_for_validator(validator_index, epoch if epoch is not None + else spec.get_current_epoch(state)) + epoch_to_sign = spec.get_randao_epoch_for_custody_period(period, validator_index) + domain = spec.get_domain(state, spec.DOMAIN_RANDAO, epoch_to_sign) + signing_root = spec.compute_signing_root(spec.Epoch(epoch_to_sign), domain) + return bls.Sign(privkeys[validator_index], signing_root) + + +def get_custody_slashable_test_vector(spec, custody_secret, length, slashable=True): + test_vector = get_custody_test_vector(length) + offset = 0 + while spec.compute_custody_bit(custody_secret, test_vector) != slashable: + offset += 1 + test_vector = test_vector = get_custody_test_vector(length, offset) + return test_vector + + +def get_custody_slashable_shard_transition(spec, start_slot, block_lengths, custody_secret, slashable=True): + shard_transition = get_shard_transition(spec, start_slot, block_lengths) + slashable_test_vector = get_custody_slashable_test_vector(spec, custody_secret, + block_lengths[0], slashable=slashable) + shard_transition.shard_data_roots[0] = ByteList[spec.MAX_SHARD_BLOCK_SIZE](slashable_test_vector) \ + .get_backing().get_left().merkle_root() + return shard_transition, slashable_test_vector diff --git a/tests/core/pyspec/eth2spec/test/phase_1/block_processing/test_process_custody_slashing.py b/tests/core/pyspec/eth2spec/test/phase_1/block_processing/test_process_custody_slashing.py index 997e5ac92..c40aa1787 100644 --- a/tests/core/pyspec/eth2spec/test/phase_1/block_processing/test_process_custody_slashing.py +++ b/tests/core/pyspec/eth2spec/test/phase_1/block_processing/test_process_custody_slashing.py @@ -1,6 +1,7 @@ from eth2spec.test.helpers.custody import ( get_valid_custody_slashing, - get_shard_transition, + get_custody_secret, + get_custody_slashable_shard_transition, ) from eth2spec.test.helpers.attestations import ( get_valid_on_time_attestation, @@ -58,9 +59,18 @@ def test_custody_slashing(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_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots)) + + validator_index = spec.get_beacon_committee( + state, + state.slot, + shard, + )[0] + custody_secret = get_custody_secret(spec, state, validator_index) + shard_transition, slashable_test_vector = get_custody_slashable_shard_transition(spec, state.slot, + [2**15 // 3] * len(offset_slots), custody_secret) + attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, - shard_transition=shard_transition, valid_custody_bits=False) + shard_transition=shard_transition) transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) @@ -68,8 +78,8 @@ def test_custody_slashing(spec, state): 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) - + slashing = get_valid_custody_slashing(spec, state, attestation, shard_transition, + custody_secret, slashable_test_vector) yield from run_custody_slashing_processing(spec, state, slashing, correct=True) @@ -79,9 +89,18 @@ def test_incorrect_custody_slashing(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_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots)) + + validator_index = spec.get_beacon_committee( + state, + state.slot, + shard, + )[0] + custody_secret = get_custody_secret(spec, state, validator_index) + shard_transition, slashable_test_vector = get_custody_slashable_shard_transition(spec, state.slot, + [2**15 // 3] * len(offset_slots), custody_secret, slashable=False) + attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, - shard_transition=shard_transition, valid_custody_bits=True) + shard_transition=shard_transition) transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) @@ -89,7 +108,8 @@ def test_incorrect_custody_slashing(spec, state): 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) + slashing = get_valid_custody_slashing(spec, state, attestation, + shard_transition, custody_secret, slashable_test_vector) yield from run_custody_slashing_processing(spec, state, slashing, correct=False) @@ -100,9 +120,18 @@ def test_multiple_epochs_custody(spec, state): transition_to(spec, state, state.slot + spec.SLOTS_PER_EPOCH * 3) shard = 0 offset_slots = spec.get_offset_slots(state, shard) - shard_transition = get_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots)) + + validator_index = spec.get_beacon_committee( + state, + state.slot, + shard, + )[0] + custody_secret = get_custody_secret(spec, state, validator_index) + shard_transition, slashable_test_vector = get_custody_slashable_shard_transition(spec, state.slot, + [2**15 // 3] * len(offset_slots), custody_secret) + attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, - shard_transition=shard_transition, valid_custody_bits=False) + shard_transition=shard_transition) transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) @@ -110,8 +139,8 @@ def test_multiple_epochs_custody(spec, state): 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) - + slashing = get_valid_custody_slashing(spec, state, attestation, shard_transition, + custody_secret, slashable_test_vector) yield from run_custody_slashing_processing(spec, state, slashing, correct=True) @@ -121,9 +150,18 @@ def test_many_epochs_custody(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_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots)) + + validator_index = spec.get_beacon_committee( + state, + state.slot, + shard, + )[0] + custody_secret = get_custody_secret(spec, state, validator_index) + shard_transition, slashable_test_vector = get_custody_slashable_shard_transition(spec, state.slot, + [2**15 // 3] * len(offset_slots), custody_secret) + attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, - shard_transition=shard_transition, valid_custody_bits=False) + shard_transition=shard_transition) transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) @@ -131,8 +169,8 @@ def test_many_epochs_custody(spec, state): 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) - + slashing = get_valid_custody_slashing(spec, state, attestation, shard_transition, + custody_secret, slashable_test_vector) yield from run_custody_slashing_processing(spec, state, slashing, correct=True) @@ -142,14 +180,23 @@ def test_off_chain_attestation(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_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots)) + + validator_index = spec.get_beacon_committee( + state, + state.slot, + shard, + )[0] + custody_secret = get_custody_secret(spec, state, validator_index) + shard_transition, slashable_test_vector = get_custody_slashable_shard_transition(spec, state.slot, + [2**15 // 3] * len(offset_slots), custody_secret) + attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, - shard_transition=shard_transition, valid_custody_bits=False) + shard_transition=shard_transition) 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) - + slashing = get_valid_custody_slashing(spec, state, attestation, shard_transition, + custody_secret, slashable_test_vector) yield from run_custody_slashing_processing(spec, state, slashing, correct=True) @@ -159,9 +206,18 @@ def test_invalid_custody_slashing(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_shard_transition(spec, state.slot, [2**15 // 3] * len(offset_slots)) + + validator_index = spec.get_beacon_committee( + state, + state.slot, + shard, + )[0] + custody_secret = get_custody_secret(spec, state, validator_index) + shard_transition, slashable_test_vector = get_custody_slashable_shard_transition(spec, state.slot, + [2**15 // 3] * len(offset_slots), custody_secret) + attestation = get_valid_on_time_attestation(spec, state, index=shard, signed=True, - shard_transition=shard_transition, valid_custody_bits=False) + shard_transition=shard_transition) transition_to(spec, state, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY) @@ -169,7 +225,8 @@ def test_invalid_custody_slashing(spec, state): 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) + slashing = get_valid_custody_slashing(spec, state, attestation, shard_transition, + custody_secret, slashable_test_vector) slashing.message.data = ByteList[spec.MAX_SHARD_BLOCK_SIZE]()