Merge branch 'fork-choice-epoch' into checkpoints
This commit is contained in:
commit
0827fbd7d5
|
@ -55,6 +55,15 @@ The head block root associated with a `store` is defined as `get_head(store)`. A
|
|||
|
||||
### Helpers
|
||||
|
||||
#### `LatestMessage`
|
||||
|
||||
```python
|
||||
@dataclass(eq=True, frozen=True)
|
||||
class LatestMessage(object):
|
||||
epoch: Epoch
|
||||
root: Hash
|
||||
```
|
||||
|
||||
#### `Store`
|
||||
|
||||
```python
|
||||
|
@ -66,7 +75,7 @@ class Store(object):
|
|||
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)
|
||||
latest_targets: Dict[ValidatorIndex, Checkpoint] = field(default_factory=dict)
|
||||
latest_messages: Dict[ValidatorIndex, LatestMessage] = field(default_factory=dict)
|
||||
```
|
||||
|
||||
#### `get_genesis_store`
|
||||
|
@ -82,7 +91,7 @@ def get_genesis_store(genesis_state: BeaconState) -> Store:
|
|||
justified_checkpoint=justified_checkpoint,
|
||||
finalized_checkpoint=finalized_checkpoint,
|
||||
blocks={root: genesis_block},
|
||||
block_states={root: genesis_state},
|
||||
block_states={root: genesis_state.copy()},
|
||||
checkpoint_states={justified_checkpoint: genesis_state.copy()},
|
||||
)
|
||||
```
|
||||
|
@ -101,10 +110,11 @@ def get_ancestor(store: Store, root: Hash, slot: Slot) -> Hash:
|
|||
```python
|
||||
def get_latest_attesting_balance(store: Store, root: Hash) -> Gwei:
|
||||
state = store.checkpoint_states[store.justified_checkpoint]
|
||||
active_indices = get_active_validator_indices(state.validator_registry, get_current_epoch(state))
|
||||
active_indices = get_active_validator_indices(state, get_current_epoch(state))
|
||||
return Gwei(sum(
|
||||
state.validator_registry[i].effective_balance for i in active_indices
|
||||
if get_ancestor(store, store.latest_targets[i].root, store.blocks[root].slot) == root
|
||||
state.validators[i].effective_balance for i in active_indices
|
||||
if (i in store.latest_messages and
|
||||
get_ancestor(store, store.latest_messages[i].root, store.blocks[root].slot) == root)
|
||||
))
|
||||
```
|
||||
|
||||
|
@ -197,8 +207,8 @@ def on_attestation(store: Store, attestation: Attestation) -> None:
|
|||
indexed_attestation = convert_to_indexed(target_state, attestation)
|
||||
validate_indexed_attestation(target_state, indexed_attestation)
|
||||
|
||||
# Update latest targets
|
||||
# Update latest messages
|
||||
for i in indexed_attestation.custody_bit_0_indices + indexed_attestation.custody_bit_1_indices:
|
||||
if i not in store.latest_targets or target.epoch > store.latest_targets[i].epoch:
|
||||
store.latest_targets[i] = target
|
||||
if i not in store.latest_messages or target.epoch > store.latest_messages[i].epoch:
|
||||
store.latest_messages[i] = LatestMessage(epoch=target.epoch, root=attestation.data.beacon_block_root)
|
||||
```
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
from eth2spec.test.context import with_all_phases, with_state, bls_switch
|
||||
from eth2spec.test.helpers.attestations import get_valid_attestation
|
||||
from eth2spec.test.helpers.block import build_empty_block_for_next_slot
|
||||
from eth2spec.test.helpers.state import state_transition_and_sign_block
|
||||
|
||||
|
||||
def add_block_to_store(spec, store, block):
|
||||
pre_state = store.block_states[block.parent_root]
|
||||
block_time = pre_state.genesis_time + block.slot * spec.SECONDS_PER_SLOT
|
||||
|
||||
if store.time < block_time:
|
||||
spec.on_tick(store, block_time)
|
||||
|
||||
spec.on_block(store, block)
|
||||
|
||||
|
||||
def add_attestation_to_store(spec, store, attestation):
|
||||
parent_block = store.blocks[attestation.data.beacon_block_root]
|
||||
pre_state = store.block_states[spec.signing_root(parent_block)]
|
||||
block_time = pre_state.genesis_time + parent_block.slot * spec.SECONDS_PER_SLOT
|
||||
next_epoch_time = block_time + spec.SLOTS_PER_EPOCH * spec.SECONDS_PER_SLOT
|
||||
|
||||
if store.time < next_epoch_time:
|
||||
spec.on_tick(store, next_epoch_time)
|
||||
|
||||
spec.on_attestation(store, attestation)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@with_state
|
||||
@bls_switch
|
||||
def test_genesis(spec, state):
|
||||
# Initialization
|
||||
store = spec.get_genesis_store(state)
|
||||
genesis_block = spec.BeaconBlock(state_root=state.hash_tree_root())
|
||||
assert spec.get_head(store) == spec.signing_root(genesis_block)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@with_state
|
||||
@bls_switch
|
||||
def test_chain_no_attestations(spec, state):
|
||||
# Initialization
|
||||
store = spec.get_genesis_store(state)
|
||||
genesis_block = spec.BeaconBlock(state_root=state.hash_tree_root())
|
||||
assert spec.get_head(store) == spec.signing_root(genesis_block)
|
||||
|
||||
# On receiving a block of `GENESIS_SLOT + 1` slot
|
||||
block_1 = build_empty_block_for_next_slot(spec, state)
|
||||
state_transition_and_sign_block(spec, state, block_1)
|
||||
add_block_to_store(spec, store, block_1)
|
||||
|
||||
# On receiving a block of next epoch
|
||||
block_2 = build_empty_block_for_next_slot(spec, state)
|
||||
state_transition_and_sign_block(spec, state, block_2)
|
||||
add_block_to_store(spec, store, block_2)
|
||||
|
||||
assert spec.get_head(store) == spec.signing_root(block_2)
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@with_state
|
||||
@bls_switch
|
||||
def test_split_tie_breaker_no_attestations(spec, state):
|
||||
genesis_state = state.copy()
|
||||
|
||||
# Initialization
|
||||
store = spec.get_genesis_store(state)
|
||||
genesis_block = spec.BeaconBlock(state_root=state.hash_tree_root())
|
||||
assert spec.get_head(store) == spec.signing_root(genesis_block)
|
||||
|
||||
# block at slot 1
|
||||
block_1_state = genesis_state.copy()
|
||||
block_1 = build_empty_block_for_next_slot(spec, block_1_state)
|
||||
state_transition_and_sign_block(spec, block_1_state, block_1)
|
||||
add_block_to_store(spec, store, block_1)
|
||||
|
||||
# additional block at slot 1
|
||||
block_2_state = genesis_state.copy()
|
||||
block_2 = build_empty_block_for_next_slot(spec, block_2_state)
|
||||
block_2.body.graffiti = b'\x42' * 32
|
||||
state_transition_and_sign_block(spec, block_2_state, block_2)
|
||||
add_block_to_store(spec, store, block_2)
|
||||
|
||||
highest_root = max(spec.signing_root(block_1), spec.signing_root(block_2))
|
||||
|
||||
assert spec.get_head(store) == highest_root
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@with_state
|
||||
@bls_switch
|
||||
def test_shorter_chain_but_heavier_weight(spec, state):
|
||||
genesis_state = state.copy()
|
||||
|
||||
# Initialization
|
||||
store = spec.get_genesis_store(state)
|
||||
genesis_block = spec.BeaconBlock(state_root=state.hash_tree_root())
|
||||
assert spec.get_head(store) == spec.signing_root(genesis_block)
|
||||
|
||||
# build longer tree
|
||||
long_state = genesis_state.copy()
|
||||
for i in range(3):
|
||||
long_block = build_empty_block_for_next_slot(spec, long_state)
|
||||
state_transition_and_sign_block(spec, long_state, long_block)
|
||||
add_block_to_store(spec, store, long_block)
|
||||
|
||||
# build short tree
|
||||
short_state = genesis_state.copy()
|
||||
short_block = build_empty_block_for_next_slot(spec, short_state)
|
||||
short_block.body.graffiti = b'\x42' * 32
|
||||
state_transition_and_sign_block(spec, short_state, short_block)
|
||||
add_block_to_store(spec, store, short_block)
|
||||
|
||||
short_attestation = get_valid_attestation(spec, short_state, short_block.slot, signed=True)
|
||||
add_attestation_to_store(spec, store, short_attestation)
|
||||
|
||||
assert spec.get_head(store) == spec.signing_root(short_block)
|
|
@ -17,10 +17,10 @@ def run_on_attestation(spec, state, store, attestation, valid=True):
|
|||
indexed_attestation = spec.convert_to_indexed(state, attestation)
|
||||
spec.on_attestation(store, attestation)
|
||||
assert (
|
||||
store.latest_targets[indexed_attestation.custody_bit_0_indices[0]] ==
|
||||
spec.Checkpoint(
|
||||
store.latest_messages[indexed_attestation.custody_bit_0_indices[0]] ==
|
||||
spec.LatestMessage(
|
||||
epoch=attestation.data.target.epoch,
|
||||
root=attestation.data.target.root,
|
||||
root=attestation.data.beacon_block_root,
|
||||
)
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in New Issue