Skip to content

Commit

Permalink
further test bounce attack
Browse files Browse the repository at this point in the history
  • Loading branch information
djrtwo committed Nov 5, 2019
1 parent 405e218 commit 97d7cf5
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 4 deletions.
5 changes: 5 additions & 0 deletions configs/mainnet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 65536
MIN_GENESIS_TIME: 1578009600


# Fork Choice
# ---------------------------------------------------------------
# 2**3 (= 8)
SAFE_SLOTS_TO_UPDATE_JUSTIFIED: 8


# Deposit contract
# ---------------------------------------------------------------
Expand Down
6 changes: 6 additions & 0 deletions configs/minimal.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 64
# Jan 3, 2020
MIN_GENESIS_TIME: 1578009600

#
#
# Fork Choice
# ---------------------------------------------------------------
# 2**1 (= 1)
SAFE_SLOTS_TO_UPDATE_JUSTIFIED: 2


# Deposit contract
Expand Down
2 changes: 1 addition & 1 deletion specs/core/0_fork-choice.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def get_head(store: Store) -> Hash:
def should_update_justified_checkpoint(store: Store, justified_checkpoint: Checkpoint) -> bool:
current_epoch = compute_epoch_at_slot(get_current_slot(store))

if get_current_slot(store) - compute_start_slot_at_epoch(current_epoch) < SAFE_SLOTS_TO_UPDATE_JUSTIFIED:
if get_current_slot(store) % SLOTS_PER_EPOCH < SAFE_SLOTS_TO_UPDATE_JUSTIFIED:
return True

justified_block = store.blocks[justified_checkpoint.root]
Expand Down
71 changes: 71 additions & 0 deletions test_libs/pyspec/eth2spec/test/fork_choice/test_on_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.queued_justified_checkpoints[0] == new_justified
60 changes: 57 additions & 3 deletions test_libs/pyspec/eth2spec/test/fork_choice/test_on_tick.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ def test_update_justified_single(spec, state):
epoch=store.justified_checkpoint.epoch + 1,
root=b'\x55' * 32,
)

store.queued_justified_checkpoints.append(new_justified)

run_on_tick(spec, store, store.time + seconds_per_epoch, new_justified)
Expand All @@ -57,16 +56,71 @@ def test_update_justified_multiple(spec, state):

@with_all_phases
@spec_state_test
def test_no_update_(spec, state):
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

new_justified = spec.Checkpoint(
epoch=store.justified_checkpoint.epoch + 1,
root=b'\x55' * 32,
)
store.queued_justified_checkpoints.append(new_justified)

# 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)

new_justified = spec.Checkpoint(
epoch=store.justified_checkpoint.epoch + 1,
root=b'\x55' * 32,
)
store.queued_justified_checkpoints.append(new_justified)

run_on_tick(spec, store, store.time + seconds_per_epoch, new_justified)
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

new_justified = spec.Checkpoint(
epoch=store.justified_checkpoint.epoch + 1,
root=b'\x55' * 32,
)
store.queued_justified_checkpoints.append(new_justified)

store.justified_checkpoint = spec.Checkpoint(
epoch=new_justified.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

new_justified = spec.Checkpoint(
epoch=store.justified_checkpoint.epoch + 1,
root=b'\x55' * 32,
)
store.queued_justified_checkpoints.append(new_justified)

store.justified_checkpoint = spec.Checkpoint(
epoch=new_justified.epoch + 1,
root=b'\44' * 32,
)

run_on_tick(spec, store, store.time + seconds_per_epoch)

0 comments on commit 97d7cf5

Please sign in to comment.