use best_justified_checkpoint instead of queued_justified_checkpoints

This commit is contained in:
Danny Ryan 2019-11-06 17:10:32 -07:00
parent 2616210637
commit fc40bff2a8
No known key found for this signature in database
GPG Key ID: 2765A792E42CE07A
3 changed files with 25 additions and 46 deletions

View File

@ -69,7 +69,7 @@ class Store(object):
genesis_time: uint64
justified_checkpoint: Checkpoint
finalized_checkpoint: Checkpoint
queued_justified_checkpoints: List[Checkpoint, 2**40] = field(default_factory=list)
best_justified_checkpoint: Checkpoint
blocks: Dict[Hash, BeaconBlock] = field(default_factory=dict)
block_states: Dict[Hash, BeaconState] = field(default_factory=dict)
checkpoint_states: Dict[Checkpoint, BeaconState] = field(default_factory=dict)
@ -89,6 +89,7 @@ def get_genesis_store(genesis_state: BeaconState) -> Store:
genesis_time=genesis_state.genesis_time,
justified_checkpoint=justified_checkpoint,
finalized_checkpoint=finalized_checkpoint,
best_justified_checkpoint=justified_checkpoint,
blocks={root: genesis_block},
block_states={root: genesis_state.copy()},
checkpoint_states={justified_checkpoint: genesis_state.copy()},
@ -147,14 +148,17 @@ def get_head(store: Store) -> Hash:
#### `should_update_justified_checkpoint`
```python
def should_update_justified_checkpoint(store: Store, justified_checkpoint: Checkpoint) -> bool:
def should_update_justified_checkpoint(store: Store, new_justified_checkpoint: Checkpoint) -> bool:
if get_current_slot(store) % SLOTS_PER_EPOCH < SAFE_SLOTS_TO_UPDATE_JUSTIFIED:
return True
justified_block = store.blocks[justified_checkpoint.root]
if justified_block.slot <= compute_start_slot_at_epoch(store.justified_checkpoint.epoch):
new_justified_block = store.blocks[new_justified_checkpoint.root]
if new_justified_block.slot <= compute_start_slot_at_epoch(store.justified_checkpoint.epoch):
return False
if not get_ancestor(store, justified_checkpoint.root, store.blocks[justified_checkpoint.root].slot):
if not (
get_ancestor(store, new_justified_checkpoint.root, store.blocks[store.justified_checkpoint.root].slot) ==
store.justified_checkpoint.root
):
return False
return True
@ -175,12 +179,9 @@ def on_tick(store: Store, time: uint64) -> None:
# Not a new epoch, return
if not (current_slot > previous_slot and current_slot % SLOTS_PER_EPOCH == 0):
return
# If new epoch and there are queued_justified_checkpoints, update if any is better than the best in store
if any(store.queued_justified_checkpoints):
best_justified_checkpoint = max(store.queued_justified_checkpoints, key=lambda checkpoint: checkpoint.epoch)
if best_justified_checkpoint.epoch > store.justified_checkpoint.epoch:
store.justified_checkpoint = best_justified_checkpoint
store.queued_justified_checkpoints = []
# Update store.justified_checkpoint if a better checkpoint is know
if store.best_justified_checkpoint.epoch > store.justified_checkpoint.epoch:
store.justified_checkpoint = store.best_justified_checkpoint
```
#### `on_block`
@ -208,10 +209,9 @@ def on_block(store: Store, block: BeaconBlock) -> None:
# Update justified checkpoint
if state.current_justified_checkpoint.epoch > store.justified_checkpoint.epoch:
store.best_justified_checkpoint = state.current_justified_checkpoint
if should_update_justified_checkpoint(store, state.current_justified_checkpoint):
store.justified_checkpoint = state.current_justified_checkpoint
else:
store.queued_justified_checkpoints.append(state.current_justified_checkpoint)
# Update finalized checkpoint
if state.finalized_checkpoint.epoch > store.finalized_checkpoint.epoch:

View File

@ -202,4 +202,4 @@ def test_on_block_outside_safe_slots_and_old_block(spec, state):
run_on_block(spec, store, block)
assert store.justified_checkpoint != new_justified
assert store.queued_justified_checkpoints[0] == new_justified
assert store.best_justified_checkpoint == new_justified

View File

@ -1,7 +1,7 @@
from eth2spec.test.context import with_all_phases, spec_state_test
def run_on_tick(spec, store, time, new_justified_checkpoint=None):
def run_on_tick(spec, store, time, new_justified_checkpoint=False):
previous_justified_checkpoint = store.justified_checkpoint
spec.on_tick(store, time)
@ -9,8 +9,9 @@ def run_on_tick(spec, store, time, new_justified_checkpoint=None):
assert store.time == time
if new_justified_checkpoint:
assert store.justified_checkpoint == 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
@ -28,30 +29,12 @@ def test_update_justified_single(spec, state):
store = spec.get_genesis_store(state)
seconds_per_epoch = spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
new_justified = spec.Checkpoint(
store.best_justified_checkpoint = 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)
@with_all_phases
@spec_state_test
def test_update_justified_multiple(spec, state):
store = spec.get_genesis_store(state)
seconds_per_epoch = spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
new_justified = None # remember checkpoint with latest epoch
for i in range(3):
new_justified = spec.Checkpoint(
epoch=store.justified_checkpoint.epoch + i + 1,
root=i.to_bytes(1, byteorder='big') * 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 + seconds_per_epoch, True)
@with_all_phases
@ -60,11 +43,10 @@ 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(
store.best_justified_checkpoint = 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
@ -77,11 +59,10 @@ def test_no_update_same_slot_at_epoch_boundary(spec, state):
def test_no_update_not_epoch_boundary(spec, state):
store = spec.get_genesis_store(state)
new_justified = spec.Checkpoint(
store.best_justified_checkpoint = 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 + spec.SECONDS_PER_SLOT)
@ -92,14 +73,13 @@ 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(
store.best_justified_checkpoint = 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,
epoch=store.best_justified_checkpoint.epoch,
root=b'\44' * 32,
)
@ -112,14 +92,13 @@ 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(
store.best_justified_checkpoint = 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,
epoch=store.best_justified_checkpoint.epoch + 1,
root=b'\44' * 32,
)