forkchoice store on top of any state now
This commit is contained in:
parent
46be6aed1d
commit
6c74468142
|
@ -14,7 +14,7 @@
|
|||
- [Helpers](#helpers)
|
||||
- [`LatestMessage`](#latestmessage)
|
||||
- [`Store`](#store)
|
||||
- [`get_genesis_store`](#get_genesis_store)
|
||||
- [`get_forkchoice_store`](#get_forkchoice_store)
|
||||
- [`get_slots_since_genesis`](#get_slots_since_genesis)
|
||||
- [`get_current_slot`](#get_current_slot)
|
||||
- [`compute_slots_since_epoch_start`](#compute_slots_since_epoch_start)
|
||||
|
@ -38,7 +38,7 @@ This document is the beacon chain fork choice spec, part of Ethereum 2.0 Phase 0
|
|||
|
||||
## Fork choice
|
||||
|
||||
The head block root associated with a `store` is defined as `get_head(store)`. At genesis, let `store = get_genesis_store(genesis_state)` and update `store` by running:
|
||||
The head block root associated with a `store` is defined as `get_head(store)`. At genesis, let `store = get_checkpoint_store(genesis_state)` and update `store` by running:
|
||||
|
||||
- `on_tick(time)` whenever `time > store.time` where `time` is the current Unix time
|
||||
- `on_block(block)` whenever a block `block: SignedBeaconBlock` is received
|
||||
|
@ -79,29 +79,35 @@ class Store(object):
|
|||
justified_checkpoint: Checkpoint
|
||||
finalized_checkpoint: Checkpoint
|
||||
best_justified_checkpoint: Checkpoint
|
||||
blocks: Dict[Root, BeaconBlock] = field(default_factory=dict)
|
||||
blocks: Dict[Root, BeaconBlockHeader] = field(default_factory=dict)
|
||||
block_states: Dict[Root, BeaconState] = field(default_factory=dict)
|
||||
checkpoint_states: Dict[Checkpoint, BeaconState] = field(default_factory=dict)
|
||||
latest_messages: Dict[ValidatorIndex, LatestMessage] = field(default_factory=dict)
|
||||
```
|
||||
|
||||
#### `get_genesis_store`
|
||||
#### `get_forkchoice_store`
|
||||
|
||||
The provided anchor-state will be regarded as a trusted state, to not roll back beyond.
|
||||
This should be the genesis state for a full client.
|
||||
|
||||
```python
|
||||
def get_genesis_store(genesis_state: BeaconState) -> Store:
|
||||
genesis_block = BeaconBlock(state_root=hash_tree_root(genesis_state))
|
||||
root = hash_tree_root(genesis_block)
|
||||
justified_checkpoint = Checkpoint(epoch=GENESIS_EPOCH, root=root)
|
||||
finalized_checkpoint = Checkpoint(epoch=GENESIS_EPOCH, root=root)
|
||||
def get_forkchoice_store(anchor_state: BeaconState) -> Store:
|
||||
anchor_block_header = anchor_state.latest_block_header.copy()
|
||||
if anchor_block_header.state_root == Bytes32():
|
||||
anchor_block_header.state_root = hash_tree_root(anchor_state)
|
||||
anchor_root = hash_tree_root(anchor_block_header)
|
||||
anchor_epoch = get_current_epoch(anchor_state)
|
||||
justified_checkpoint = Checkpoint(epoch=anchor_epoch, root=anchor_root)
|
||||
finalized_checkpoint = Checkpoint(epoch=anchor_epoch, root=anchor_root)
|
||||
return Store(
|
||||
time=genesis_state.genesis_time,
|
||||
genesis_time=genesis_state.genesis_time,
|
||||
time=anchor_state.genesis_time,
|
||||
genesis_time=anchor_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()},
|
||||
blocks={anchor_root: anchor_block_header},
|
||||
block_states={anchor_root: anchor_state.copy()},
|
||||
checkpoint_states={justified_checkpoint: anchor_state.copy()},
|
||||
)
|
||||
```
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ def add_attestation_to_store(spec, store, attestation):
|
|||
@spec_state_test
|
||||
def test_genesis(spec, state):
|
||||
# Initialization
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
genesis_block = spec.BeaconBlock(state_root=state.hash_tree_root())
|
||||
assert spec.get_head(store) == spec.hash_tree_root(genesis_block)
|
||||
|
||||
|
@ -43,7 +43,7 @@ def test_genesis(spec, state):
|
|||
@spec_state_test
|
||||
def test_chain_no_attestations(spec, state):
|
||||
# Initialization
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
genesis_block = spec.BeaconBlock(state_root=state.hash_tree_root())
|
||||
assert spec.get_head(store) == spec.hash_tree_root(genesis_block)
|
||||
|
||||
|
@ -66,7 +66,7 @@ def test_split_tie_breaker_no_attestations(spec, state):
|
|||
genesis_state = state.copy()
|
||||
|
||||
# Initialization
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
genesis_block = spec.BeaconBlock(state_root=state.hash_tree_root())
|
||||
assert spec.get_head(store) == spec.hash_tree_root(genesis_block)
|
||||
|
||||
|
@ -94,7 +94,7 @@ def test_shorter_chain_but_heavier_weight(spec, state):
|
|||
genesis_state = state.copy()
|
||||
|
||||
# Initialization
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
genesis_block = spec.BeaconBlock(state_root=state.hash_tree_root())
|
||||
assert spec.get_head(store) == spec.hash_tree_root(genesis_block)
|
||||
|
||||
|
@ -123,7 +123,7 @@ def test_shorter_chain_but_heavier_weight(spec, state):
|
|||
def test_filtered_block_tree(spec, state):
|
||||
# Initialization
|
||||
genesis_state_root = state.hash_tree_root()
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
genesis_block = spec.BeaconBlock(state_root=genesis_state_root)
|
||||
|
||||
# transition state past initial couple of epochs
|
||||
|
|
|
@ -27,7 +27,7 @@ def run_on_attestation(spec, state, store, attestation, valid=True):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_on_attestation_current_epoch(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
spec.on_tick(store, store.time + spec.SECONDS_PER_SLOT * 2)
|
||||
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
|
@ -46,7 +46,7 @@ def test_on_attestation_current_epoch(spec, state):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_on_attestation_previous_epoch(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_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)
|
||||
|
@ -65,7 +65,7 @@ def test_on_attestation_previous_epoch(spec, state):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_on_attestation_past_epoch(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
|
||||
# move time forward 2 epochs
|
||||
time = store.time + 2 * spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
|
@ -87,7 +87,7 @@ def test_on_attestation_past_epoch(spec, state):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_on_attestation_mismatched_target_and_slot(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_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)
|
||||
|
@ -110,7 +110,7 @@ def test_on_attestation_mismatched_target_and_slot(spec, state):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_on_attestation_target_not_in_store(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
time = spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
spec.on_tick(store, time)
|
||||
|
||||
|
@ -131,7 +131,7 @@ def test_on_attestation_target_not_in_store(spec, state):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_on_attestation_beacon_block_not_in_store(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
time = spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
spec.on_tick(store, time)
|
||||
|
||||
|
@ -159,7 +159,7 @@ def test_on_attestation_beacon_block_not_in_store(spec, state):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_on_attestation_future_epoch(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
time = 3 * spec.SECONDS_PER_SLOT
|
||||
spec.on_tick(store, time)
|
||||
|
||||
|
@ -179,7 +179,7 @@ def test_on_attestation_future_epoch(spec, state):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_on_attestation_future_block(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
time = spec.SECONDS_PER_SLOT * 5
|
||||
spec.on_tick(store, time)
|
||||
|
||||
|
@ -199,7 +199,7 @@ def test_on_attestation_future_block(spec, state):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_on_attestation_same_slot(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
time = 1 * spec.SECONDS_PER_SLOT
|
||||
spec.on_tick(store, time)
|
||||
|
||||
|
@ -215,7 +215,7 @@ def test_on_attestation_same_slot(spec, state):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_on_attestation_invalid_attestation(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
time = 3 * spec.SECONDS_PER_SLOT
|
||||
spec.on_tick(store, time)
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ def apply_next_epoch_with_attestations(spec, state, store):
|
|||
@spec_state_test
|
||||
def test_basic(spec, state):
|
||||
# Initialization
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
time = 100
|
||||
spec.on_tick(store, time)
|
||||
assert store.time == time
|
||||
|
@ -60,7 +60,7 @@ def test_basic(spec, state):
|
|||
@spec_state_test
|
||||
def test_on_block_checkpoints(spec, state):
|
||||
# Initialization
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
time = 100
|
||||
spec.on_tick(store, time)
|
||||
|
||||
|
@ -86,7 +86,7 @@ def test_on_block_checkpoints(spec, state):
|
|||
@spec_state_test
|
||||
def test_on_block_future_block(spec, state):
|
||||
# Initialization
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
|
||||
# do not tick time
|
||||
|
||||
|
@ -100,7 +100,7 @@ def test_on_block_future_block(spec, state):
|
|||
@spec_state_test
|
||||
def test_on_block_bad_parent_root(spec, state):
|
||||
# Initialization
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
time = 100
|
||||
spec.on_tick(store, time)
|
||||
|
||||
|
@ -120,7 +120,7 @@ def test_on_block_bad_parent_root(spec, state):
|
|||
@spec_state_test
|
||||
def test_on_block_before_finalized(spec, state):
|
||||
# Initialization
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
time = 100
|
||||
spec.on_tick(store, time)
|
||||
|
||||
|
@ -139,7 +139,7 @@ def test_on_block_before_finalized(spec, state):
|
|||
@spec_state_test
|
||||
def test_on_block_update_justified_checkpoint_within_safe_slots(spec, state):
|
||||
# Initialization
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
time = 100
|
||||
spec.on_tick(store, time)
|
||||
|
||||
|
@ -170,7 +170,7 @@ def test_on_block_update_justified_checkpoint_within_safe_slots(spec, state):
|
|||
@spec_state_test
|
||||
def test_on_block_outside_safe_slots_and_multiple_better_justified(spec, state):
|
||||
# Initialization
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
time = 100
|
||||
spec.on_tick(store, time)
|
||||
|
||||
|
|
|
@ -19,14 +19,14 @@ def run_on_tick(spec, store, time, new_justified_checkpoint=False):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_basic(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_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)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
seconds_per_epoch = spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
|
||||
store.best_justified_checkpoint = spec.Checkpoint(
|
||||
|
@ -40,7 +40,7 @@ def test_update_justified_single(spec, state):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_no_update_same_slot_at_epoch_boundary(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
seconds_per_epoch = spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
|
||||
store.best_justified_checkpoint = spec.Checkpoint(
|
||||
|
@ -57,7 +57,7 @@ def test_no_update_same_slot_at_epoch_boundary(spec, state):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_no_update_not_epoch_boundary(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
|
||||
store.best_justified_checkpoint = spec.Checkpoint(
|
||||
epoch=store.justified_checkpoint.epoch + 1,
|
||||
|
@ -70,7 +70,7 @@ def test_no_update_not_epoch_boundary(spec, state):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_no_update_new_justified_equal_epoch(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
seconds_per_epoch = spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
|
||||
store.best_justified_checkpoint = spec.Checkpoint(
|
||||
|
@ -89,7 +89,7 @@ def test_no_update_new_justified_equal_epoch(spec, state):
|
|||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_no_update_new_justified_later_epoch(spec, state):
|
||||
store = spec.get_genesis_store(state)
|
||||
store = spec.get_forkchoice_store(state)
|
||||
seconds_per_epoch = spec.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
|
||||
store.best_justified_checkpoint = spec.Checkpoint(
|
||||
|
|
Loading…
Reference in New Issue