mirror of
https://github.com/ethereum/consensus-specs.git
synced 2026-02-02 17:35:03 -05:00
Backport master (v0.9.1) to dev (#1482)
* p2p-interface: clarify that signing_root is used for block requests * hash cleanups * one more hash tree root gone for blocks - block hashes are always signing roots! * use simple serialize data types consistently * Describe which finalized root/epoch to use * remove custody_bits from attestation * remove AttestationDataAndCustodyBit * Specify inclusive range for genesis deposits * add initial fork choice bounce prevention and tests * PR feedback * further test bounce attack * wipe queued justified after epoch transition * remove extra var * minor fmt * only allow attestatiosn to be considered from current and previous epoch * use best_justified_checkpoint instead of queued_justified_checkpoints * use helper for slots since epoch start * be explicit about use of genesis epoch for previous epoch in fork choice on_block * pr feedback * add note aboutgenesis attestations * cleanup get_eth1_vote * make eth1_follow_distance clearer * Update the expected proposer period Since `SECONDS_PER_SLOT` is now `12` * minor fix to comment in mainnet config * Update 0_beacon-chain.md
This commit is contained in:
committed by
vbuterin
parent
40cb72ec11
commit
b15669b7a5
@@ -9,7 +9,7 @@ def test_decoder():
|
||||
rng = Random(123)
|
||||
|
||||
# check these types only, Block covers a lot of operation types already.
|
||||
for typ in [spec.AttestationDataAndCustodyBit, spec.BeaconState, spec.BeaconBlock]:
|
||||
for typ in [spec.Attestation, spec.BeaconState, spec.BeaconBlock]:
|
||||
# create a random pyspec value
|
||||
original = random_value.get_random_ssz_object(rng, typ, 100, 10,
|
||||
mode=random_value.RandomizationMode.mode_random,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
|
||||
from eth2spec.test.context import with_all_phases, spec_state_test, with_phases
|
||||
|
||||
|
||||
from eth2spec.test.context import with_all_phases, spec_state_test
|
||||
from eth2spec.test.helpers.block import build_empty_block_for_next_slot
|
||||
from eth2spec.test.helpers.attestations import get_valid_attestation
|
||||
from eth2spec.test.helpers.state import state_transition_and_sign_block
|
||||
@@ -19,7 +17,7 @@ def run_on_attestation(spec, state, store, attestation, valid=True):
|
||||
indexed_attestation = spec.get_indexed_attestation(state, attestation)
|
||||
spec.on_attestation(store, attestation)
|
||||
assert (
|
||||
store.latest_messages[indexed_attestation.custody_bit_0_indices[0]] ==
|
||||
store.latest_messages[indexed_attestation.attesting_indices[0]] ==
|
||||
spec.LatestMessage(
|
||||
epoch=attestation.data.target.epoch,
|
||||
root=attestation.data.beacon_block_root,
|
||||
@@ -29,10 +27,9 @@ def run_on_attestation(spec, state, store, attestation, valid=True):
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_on_attestation(spec, state):
|
||||
def test_on_attestation_current_epoch(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
time = 100
|
||||
spec.on_tick(store, time)
|
||||
spec.on_tick(store, store.time + spec.SECONDS_PER_SLOT * 2)
|
||||
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
state_transition_and_sign_block(spec, state, block)
|
||||
@@ -41,9 +38,53 @@ def test_on_attestation(spec, state):
|
||||
spec.on_block(store, block)
|
||||
|
||||
attestation = get_valid_attestation(spec, state, slot=block.slot)
|
||||
assert attestation.data.target.epoch == spec.GENESIS_EPOCH
|
||||
assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == spec.GENESIS_EPOCH
|
||||
|
||||
run_on_attestation(spec, state, store, attestation)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_on_attestation_previous_epoch(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
spec.on_tick(store, store.time + spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH)
|
||||
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
state_transition_and_sign_block(spec, state, block)
|
||||
|
||||
# store block in store
|
||||
spec.on_block(store, block)
|
||||
|
||||
attestation = get_valid_attestation(spec, state, slot=block.slot)
|
||||
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)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_on_attestation_past_epoch(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
|
||||
# move time forward 2 epochs
|
||||
time = store.time + 2 * spec.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)
|
||||
state_transition_and_sign_block(spec, state, block)
|
||||
spec.on_block(store, block)
|
||||
|
||||
# create attestation for past block
|
||||
attestation = get_valid_attestation(spec, state, slot=state.slot)
|
||||
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)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_on_attestation_target_not_in_store(spec, state):
|
||||
@@ -77,8 +118,7 @@ def test_on_attestation_future_epoch(spec, state):
|
||||
spec.on_block(store, block)
|
||||
|
||||
# move state forward but not store
|
||||
attestation_slot = block.slot + spec.SLOTS_PER_EPOCH
|
||||
state.slot = attestation_slot
|
||||
state.slot = block.slot + spec.SLOTS_PER_EPOCH
|
||||
|
||||
attestation = get_valid_attestation(spec, state, slot=state.slot)
|
||||
run_on_attestation(spec, state, store, attestation, False)
|
||||
@@ -100,7 +140,7 @@ def test_on_attestation_same_slot(spec, state):
|
||||
run_on_attestation(spec, state, store, attestation, False)
|
||||
|
||||
|
||||
@with_phases(['phase0'])
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_on_attestation_invalid_attestation(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
@@ -113,6 +153,7 @@ def test_on_attestation_invalid_attestation(spec, state):
|
||||
spec.on_block(store, block)
|
||||
|
||||
attestation = get_valid_attestation(spec, state, slot=block.slot)
|
||||
# make attestation invalid by setting a phase1-only custody bit
|
||||
attestation.custody_bits[0] = 1
|
||||
# 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)
|
||||
|
||||
@@ -132,3 +132,74 @@ def test_on_block_before_finalized(spec, state):
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
state_transition_and_sign_block(spec, state, block)
|
||||
run_on_block(spec, store, block, False)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_on_block_update_justified_checkpoint_within_safe_slots(spec, state):
|
||||
# Initialization
|
||||
store = spec.get_genesis_store(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_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 = signing_root(last_block)
|
||||
|
||||
# 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)
|
||||
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, block)
|
||||
|
||||
assert store.justified_checkpoint == new_justified
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_on_block_outside_safe_slots_and_old_block(spec, state):
|
||||
# Initialization
|
||||
store = spec.get_genesis_store(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_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 = signing_root(last_block)
|
||||
|
||||
# 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
|
||||
|
||||
# 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=just_block.hash_tree_root(),
|
||||
)
|
||||
just_state.current_justified_checkpoint = new_justified
|
||||
|
||||
block = build_empty_block_for_next_slot(spec, just_state)
|
||||
state_transition_and_sign_block(spec, deepcopy(just_state), block)
|
||||
|
||||
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
|
||||
run_on_block(spec, store, block)
|
||||
|
||||
assert store.justified_checkpoint != new_justified
|
||||
assert store.best_justified_checkpoint == new_justified
|
||||
|
||||
105
test_libs/pyspec/eth2spec/test/fork_choice/test_on_tick.py
Normal file
105
test_libs/pyspec/eth2spec/test/fork_choice/test_on_tick.py
Normal file
@@ -0,0 +1,105 @@
|
||||
from eth2spec.test.context import with_all_phases, spec_state_test
|
||||
|
||||
|
||||
def run_on_tick(spec, store, time, new_justified_checkpoint=False):
|
||||
previous_justified_checkpoint = store.justified_checkpoint
|
||||
|
||||
spec.on_tick(store, time)
|
||||
|
||||
assert store.time == time
|
||||
|
||||
if new_justified_checkpoint:
|
||||
assert store.justified_checkpoint == store.best_justified_checkpoint
|
||||
assert store.justified_checkpoint.epoch > previous_justified_checkpoint.epoch
|
||||
assert store.justified_checkpoint.root != previous_justified_checkpoint.root
|
||||
else:
|
||||
assert store.justified_checkpoint == previous_justified_checkpoint
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_basic(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
run_on_tick(spec, store, store.time + 1)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_update_justified_single(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
seconds_per_epoch = spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
|
||||
store.best_justified_checkpoint = spec.Checkpoint(
|
||||
epoch=store.justified_checkpoint.epoch + 1,
|
||||
root=b'\x55' * 32,
|
||||
)
|
||||
|
||||
run_on_tick(spec, store, store.time + seconds_per_epoch, True)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_no_update_same_slot_at_epoch_boundary(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
seconds_per_epoch = spec.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)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_no_update_not_epoch_boundary(spec, state):
|
||||
store = spec.get_genesis_store(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.SECONDS_PER_SLOT)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_no_update_new_justified_equal_epoch(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
seconds_per_epoch = spec.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,
|
||||
root=b'\44' * 32,
|
||||
)
|
||||
|
||||
run_on_tick(spec, store, store.time + seconds_per_epoch)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_no_update_new_justified_later_epoch(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
seconds_per_epoch = spec.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)
|
||||
@@ -54,11 +54,9 @@ def get_valid_attestation(spec, state, slot=None, index=None, signed=False):
|
||||
|
||||
committee_size = len(beacon_committee)
|
||||
aggregation_bits = Bitlist[spec.MAX_VALIDATORS_PER_COMMITTEE](*([0] * committee_size))
|
||||
custody_bits = Bitlist[spec.MAX_VALIDATORS_PER_COMMITTEE](*([0] * committee_size))
|
||||
attestation = spec.Attestation(
|
||||
aggregation_bits=aggregation_bits,
|
||||
data=attestation_data,
|
||||
custody_bits=custody_bits,
|
||||
)
|
||||
fill_aggregate_attestation(spec, state, attestation)
|
||||
if signed:
|
||||
@@ -83,7 +81,7 @@ def sign_aggregate_attestation(spec, state, attestation_data, participants: List
|
||||
|
||||
|
||||
def sign_indexed_attestation(spec, state, indexed_attestation):
|
||||
participants = indexed_attestation.custody_bit_0_indices + indexed_attestation.custody_bit_1_indices
|
||||
participants = indexed_attestation.attesting_indices
|
||||
indexed_attestation.signature = sign_aggregate_attestation(spec, state, indexed_attestation.data, participants)
|
||||
|
||||
|
||||
@@ -97,14 +95,9 @@ def sign_attestation(spec, state, attestation):
|
||||
attestation.signature = sign_aggregate_attestation(spec, state, attestation.data, participants)
|
||||
|
||||
|
||||
def get_attestation_signature(spec, state, attestation_data, privkey, custody_bit=0b0):
|
||||
message_hash = spec.AttestationDataAndCustodyBit(
|
||||
data=attestation_data,
|
||||
custody_bit=custody_bit,
|
||||
).hash_tree_root()
|
||||
|
||||
def get_attestation_signature(spec, state, attestation_data, privkey):
|
||||
return bls_sign(
|
||||
message_hash=message_hash,
|
||||
message_hash=attestation_data.hash_tree_root(),
|
||||
privkey=privkey,
|
||||
domain=spec.get_domain(
|
||||
state=state,
|
||||
|
||||
@@ -2,7 +2,7 @@ from eth2spec.test.context import (
|
||||
spec_state_test,
|
||||
expect_assertion_error,
|
||||
always_bls, never_bls,
|
||||
with_all_phases, with_phases,
|
||||
with_all_phases,
|
||||
spec_test,
|
||||
low_balances,
|
||||
with_custom_state,
|
||||
@@ -274,35 +274,6 @@ def test_bad_source_root(spec, state):
|
||||
yield from run_attestation_processing(spec, state, attestation, False)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_inconsistent_bits(spec, state):
|
||||
attestation = get_valid_attestation(spec, state)
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
|
||||
custody_bits = attestation.custody_bits[:]
|
||||
custody_bits.append(False)
|
||||
|
||||
attestation.custody_bits = custody_bits
|
||||
|
||||
sign_attestation(spec, state, attestation)
|
||||
|
||||
yield from run_attestation_processing(spec, state, attestation, False)
|
||||
|
||||
|
||||
@with_phases(['phase0'])
|
||||
@spec_state_test
|
||||
def test_non_empty_custody_bits(spec, state):
|
||||
attestation = get_valid_attestation(spec, state)
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
|
||||
attestation.custody_bits = attestation.aggregation_bits[:]
|
||||
|
||||
sign_attestation(spec, state, attestation)
|
||||
|
||||
yield from run_attestation_processing(spec, state, attestation, False)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_empty_aggregation_bits(spec, state):
|
||||
@@ -344,32 +315,3 @@ def test_too_few_aggregation_bits(spec, state):
|
||||
attestation.aggregation_bits = attestation.aggregation_bits[:-1]
|
||||
|
||||
yield from run_attestation_processing(spec, state, attestation, False)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_too_many_custody_bits(spec, state):
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
|
||||
# one too many bits
|
||||
attestation.custody_bits.append(0b0)
|
||||
|
||||
yield from run_attestation_processing(spec, state, attestation, False)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_too_few_custody_bits(spec, state):
|
||||
attestation = get_valid_attestation(spec, state)
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
|
||||
attestation.custody_bits = Bitlist[spec.MAX_VALIDATORS_PER_COMMITTEE](
|
||||
*([0b1] + [0b0] * (len(attestation.custody_bits) - 1)))
|
||||
|
||||
sign_attestation(spec, state, attestation)
|
||||
|
||||
# one too few bits
|
||||
attestation.custody_bits = attestation.custody_bits[:-1]
|
||||
|
||||
yield from run_attestation_processing(spec, state, attestation, False)
|
||||
|
||||
@@ -25,10 +25,7 @@ def run_attester_slashing_processing(spec, state, attester_slashing, valid=True)
|
||||
yield 'post', None
|
||||
return
|
||||
|
||||
slashed_indices = (
|
||||
attester_slashing.attestation_1.custody_bit_0_indices
|
||||
+ attester_slashing.attestation_1.custody_bit_1_indices
|
||||
)
|
||||
slashed_indices = attester_slashing.attestation_1.attesting_indices
|
||||
|
||||
proposer_index = spec.get_beacon_proposer_index(state)
|
||||
pre_proposer_balance = get_balance(state, proposer_index)
|
||||
@@ -112,10 +109,7 @@ def test_success_surround(spec, state):
|
||||
@always_bls
|
||||
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.custody_bit_0_indices
|
||||
+ attester_slashing.attestation_1.custody_bit_1_indices
|
||||
)
|
||||
slashed_indices = attester_slashing.attestation_1.attesting_indices
|
||||
for index in slashed_indices:
|
||||
spec.initiate_validator_exit(state, index)
|
||||
|
||||
@@ -127,10 +121,7 @@ def test_success_already_exited_recent(spec, state):
|
||||
@always_bls
|
||||
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.custody_bit_0_indices
|
||||
+ attester_slashing.attestation_1.custody_bit_1_indices
|
||||
)
|
||||
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
|
||||
@@ -190,38 +181,23 @@ 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
|
||||
attestation_1 = attester_slashing.attestation_1
|
||||
validator_indices = attestation_1.custody_bit_0_indices + attestation_1.custody_bit_1_indices
|
||||
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)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_custody_bit_0_and_1_intersect(spec, state):
|
||||
attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True)
|
||||
|
||||
attester_slashing.attestation_1.custody_bit_1_indices.append(
|
||||
attester_slashing.attestation_1.custody_bit_0_indices[0]
|
||||
)
|
||||
|
||||
sign_indexed_attestation(spec, state, attester_slashing.attestation_1)
|
||||
|
||||
yield from run_attester_slashing_processing(spec, state, attester_slashing, False)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
@always_bls
|
||||
def test_att1_bad_extra_index(spec, state):
|
||||
attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True)
|
||||
|
||||
indices = attester_slashing.attestation_1.custody_bit_0_indices
|
||||
indices = attester_slashing.attestation_1.attesting_indices
|
||||
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.custody_bit_0_indices = sorted(indices)
|
||||
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.
|
||||
|
||||
@@ -234,10 +210,10 @@ def test_att1_bad_extra_index(spec, state):
|
||||
def test_att1_bad_replaced_index(spec, state):
|
||||
attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True)
|
||||
|
||||
indices = attester_slashing.attestation_1.custody_bit_0_indices
|
||||
indices = attester_slashing.attestation_1.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_1.custody_bit_0_indices = sorted(indices)
|
||||
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 replaced index is spotted, and slashing is aborted.
|
||||
|
||||
@@ -250,10 +226,10 @@ def test_att1_bad_replaced_index(spec, state):
|
||||
def test_att2_bad_extra_index(spec, state):
|
||||
attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True)
|
||||
|
||||
indices = attester_slashing.attestation_2.custody_bit_0_indices
|
||||
indices = attester_slashing.attestation_2.attesting_indices
|
||||
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_2.custody_bit_0_indices = sorted(indices)
|
||||
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 extra index is spotted, and slashing is aborted.
|
||||
|
||||
@@ -266,10 +242,10 @@ def test_att2_bad_extra_index(spec, state):
|
||||
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.custody_bit_0_indices
|
||||
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.custody_bit_0_indices = sorted(indices)
|
||||
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.
|
||||
|
||||
@@ -278,10 +254,10 @@ def test_att2_bad_replaced_index(spec, state):
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_unsorted_att_1_bit0(spec, state):
|
||||
def test_unsorted_att_1(spec, state):
|
||||
attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True)
|
||||
|
||||
indices = attester_slashing.attestation_1.custody_bit_0_indices
|
||||
indices = attester_slashing.attestation_1.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_1)
|
||||
@@ -291,15 +267,12 @@ def test_unsorted_att_1_bit0(spec, state):
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_unsorted_att_2_bit0(spec, state):
|
||||
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.custody_bit_0_indices
|
||||
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)
|
||||
|
||||
|
||||
# note: unsorted indices for custody bit 0 are to be introduced in phase 1 testing.
|
||||
|
||||
@@ -141,7 +141,7 @@ def test_duplicate_attestation(spec, state):
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
|
||||
indexed_attestation = spec.get_indexed_attestation(state, attestation)
|
||||
participants = indexed_attestation.custody_bit_0_indices + indexed_attestation.custody_bit_1_indices
|
||||
participants = indexed_attestation.attesting_indices
|
||||
|
||||
assert len(participants) > 0
|
||||
|
||||
|
||||
@@ -188,8 +188,7 @@ def test_attester_slashing(spec, state):
|
||||
pre_state = deepcopy(state)
|
||||
|
||||
attester_slashing = get_valid_attester_slashing(spec, state, signed_1=True, signed_2=True)
|
||||
validator_index = (attester_slashing.attestation_1.custody_bit_0_indices
|
||||
+ attester_slashing.attestation_1.custody_bit_1_indices)[0]
|
||||
validator_index = attester_slashing.attestation_1.attesting_indices[0]
|
||||
|
||||
assert not state.validators[validator_index].slashed
|
||||
|
||||
|
||||
Reference in New Issue
Block a user