diff --git a/specs/bellatrix/fork-choice.md b/specs/bellatrix/fork-choice.md index 88f4e5c39..fd70cfff4 100644 --- a/specs/bellatrix/fork-choice.md +++ b/specs/bellatrix/fork-choice.md @@ -271,11 +271,15 @@ def on_block(store: Store, signed_block: SignedBeaconBlock) -> None: # Add new state for this block to the store store.block_states[block_root] = state - # Add proposer score boost if the block is timely + # Add block timeliness to the store time_into_slot = (store.time - store.genesis_time) % SECONDS_PER_SLOT is_before_attesting_interval = time_into_slot < SECONDS_PER_SLOT // INTERVALS_PER_SLOT + is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval + store.block_timeliness[hash_tree_root(block)] = is_timely + + # Add proposer score boost if the block is timely and not conflicting with an existing block is_first_block = store.proposer_boost_root == Root() - if get_current_slot(store) == block.slot and is_before_attesting_interval and is_first_block: + if is_timely and is_first_block: store.proposer_boost_root = hash_tree_root(block) # Update checkpoints in store if necessary diff --git a/specs/capella/fork-choice.md b/specs/capella/fork-choice.md index a830080c1..ded9782cc 100644 --- a/specs/capella/fork-choice.md +++ b/specs/capella/fork-choice.md @@ -103,11 +103,15 @@ def on_block(store: Store, signed_block: SignedBeaconBlock) -> None: # Add new state for this block to the store store.block_states[block_root] = state - # Add proposer score boost if the block is timely + # Add block timeliness to the store time_into_slot = (store.time - store.genesis_time) % SECONDS_PER_SLOT is_before_attesting_interval = time_into_slot < SECONDS_PER_SLOT // INTERVALS_PER_SLOT + is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval + store.block_timeliness[hash_tree_root(block)] = is_timely + + # Add proposer score boost if the block is timely and not conflicting with an existing block is_first_block = store.proposer_boost_root == Root() - if get_current_slot(store) == block.slot and is_before_attesting_interval and is_first_block: + if is_timely and is_first_block: store.proposer_boost_root = hash_tree_root(block) # Update checkpoints in store if necessary diff --git a/specs/deneb/fork-choice.md b/specs/deneb/fork-choice.md index 5a700cc7a..03b3bf8fe 100644 --- a/specs/deneb/fork-choice.md +++ b/specs/deneb/fork-choice.md @@ -103,11 +103,15 @@ def on_block(store: Store, signed_block: SignedBeaconBlock) -> None: # Add new state for this block to the store store.block_states[block_root] = state - # Add proposer score boost if the block is timely + # Add block timeliness to the store time_into_slot = (store.time - store.genesis_time) % SECONDS_PER_SLOT is_before_attesting_interval = time_into_slot < SECONDS_PER_SLOT // INTERVALS_PER_SLOT + is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval + store.block_timeliness[hash_tree_root(block)] = is_timely + + # Add proposer score boost if the block is timely and not conflicting with an existing block is_first_block = store.proposer_boost_root == Root() - if get_current_slot(store) == block.slot and is_before_attesting_interval and is_first_block: + if is_timely and is_first_block: store.proposer_boost_root = hash_tree_root(block) # Update checkpoints in store if necessary diff --git a/specs/phase0/fork-choice.md b/specs/phase0/fork-choice.md index 5dea585d1..077209d5f 100644 --- a/specs/phase0/fork-choice.md +++ b/specs/phase0/fork-choice.md @@ -25,18 +25,17 @@ - [`filter_block_tree`](#filter_block_tree) - [`get_filtered_block_tree`](#get_filtered_block_tree) - [`get_head`](#get_head) + - [`update_checkpoints`](#update_checkpoints) + - [`update_unrealized_checkpoints`](#update_unrealized_checkpoints) - [Proposer head and reorg helpers](#proposer-head-and-reorg-helpers) - [`is_head_late`](#is_head_late) - [`is_shuffling_stable`](#is_shuffling_stable) - - [`is_shuffling_stable`](#is_shuffling_stable-1) - [`is_ffg_competitive`](#is_ffg_competitive) - [`is_finalization_ok`](#is_finalization_ok) - [`is_proposing_on_time`](#is_proposing_on_time) - [`is_head_weak`](#is_head_weak) - [`is_parent_strong`](#is_parent_strong) - [`get_proposer_head`](#get_proposer_head) - - [`update_checkpoints`](#update_checkpoints) - - [`update_unrealized_checkpoints`](#update_unrealized_checkpoints) - [Pull-up tip helpers](#pull-up-tip-helpers) - [`compute_pulled_up_tip`](#compute_pulled_up_tip) - [`on_tick` helpers](#on_tick-helpers) @@ -365,6 +364,38 @@ def get_head(store: Store) -> Root: head = max(children, key=lambda root: (get_weight(store, root), root)) ``` +#### `update_checkpoints` + +```python +def update_checkpoints(store: Store, justified_checkpoint: Checkpoint, finalized_checkpoint: Checkpoint) -> None: + """ + Update checkpoints in store if necessary + """ + # Update justified checkpoint + if justified_checkpoint.epoch > store.justified_checkpoint.epoch: + store.justified_checkpoint = justified_checkpoint + + # Update finalized checkpoint + if finalized_checkpoint.epoch > store.finalized_checkpoint.epoch: + store.finalized_checkpoint = finalized_checkpoint +``` + +#### `update_unrealized_checkpoints` + +```python +def update_unrealized_checkpoints(store: Store, unrealized_justified_checkpoint: Checkpoint, + unrealized_finalized_checkpoint: Checkpoint) -> None: + """ + Update unrealized checkpoints in store if necessary + """ + # Update unrealized justified checkpoint + if unrealized_justified_checkpoint.epoch > store.unrealized_justified_checkpoint.epoch: + store.unrealized_justified_checkpoint = unrealized_justified_checkpoint + + # Update unrealized finalized checkpoint + if unrealized_finalized_checkpoint.epoch > store.unrealized_finalized_checkpoint.epoch: + store.unrealized_finalized_checkpoint = unrealized_finalized_checkpoint +``` #### Proposer head and reorg helpers _Implementing these helpers is optional_. @@ -372,13 +403,7 @@ _Implementing these helpers is optional_. ##### `is_head_late` ```python def is_head_late(store: Store, head_root: Root) -> bool: - return not store.block_timeliness.get(head_root) -``` - -##### `is_shuffling_stable` -```python -def is_shuffling_stable(slot: Slot) -> bool: - return slot % SLOTS_PER_EPOCH != 0 + return not store.block_timeliness[head_root] ``` ##### `is_shuffling_stable` @@ -478,41 +503,6 @@ def get_proposer_head(store: Store, head_root: Root, slot: Slot) -> Root: optimize by re-ordering the conditions from least to most expensive and by returning early if any of the early conditions are `False`. - -#### `update_checkpoints` - -```python -def update_checkpoints(store: Store, justified_checkpoint: Checkpoint, finalized_checkpoint: Checkpoint) -> None: - """ - Update checkpoints in store if necessary - """ - # Update justified checkpoint - if justified_checkpoint.epoch > store.justified_checkpoint.epoch: - store.justified_checkpoint = justified_checkpoint - - # Update finalized checkpoint - if finalized_checkpoint.epoch > store.finalized_checkpoint.epoch: - store.finalized_checkpoint = finalized_checkpoint -``` - -#### `update_unrealized_checkpoints` - -```python -def update_unrealized_checkpoints(store: Store, unrealized_justified_checkpoint: Checkpoint, - unrealized_finalized_checkpoint: Checkpoint) -> None: - """ - Update unrealized checkpoints in store if necessary - """ - # Update unrealized justified checkpoint - if unrealized_justified_checkpoint.epoch > store.unrealized_justified_checkpoint.epoch: - store.unrealized_justified_checkpoint = unrealized_justified_checkpoint - - # Update unrealized finalized checkpoint - if unrealized_finalized_checkpoint.epoch > store.unrealized_finalized_checkpoint.epoch: - store.unrealized_finalized_checkpoint = unrealized_finalized_checkpoint -``` - - #### Pull-up tip helpers ##### `compute_pulled_up_tip`