1616 - [ New ` validate_inclusion_lists ` ] ( #new-validate_inclusion_lists )
1717 - [ New ` get_attester_head ` ] ( #new-get_attester_head )
1818 - [ Modified ` get_proposer_head ` ] ( #modified-get_proposer_head )
19+ - [ Updated fork-choice helpers] ( #updated-fork-choice-helpers )
20+ - [ Modified ` update_proposer_boost_root ` ] ( #modified-update_proposer_boost_root )
1921- [ New fork-choice helpers] ( #new-fork-choice-helpers )
2022 - [ New ` get_view_freeze_cutoff_ms ` ] ( #new-get_view_freeze_cutoff_ms )
2123 - [ New ` get_inclusion_list_submission_due_ms ` ] ( #new-get_inclusion_list_submission_due_ms )
2224 - [ New ` get_proposer_inclusion_list_cutoff_ms ` ] ( #new-get_proposer_inclusion_list_cutoff_ms )
25+ - [ New ` record_block_inclusion_list_satisfaction ` ] ( #new-record_block_inclusion_list_satisfaction )
2326- [ Updated fork-choice handlers] ( #updated-fork-choice-handlers )
2427 - [ New ` on_inclusion_list ` ] ( #new-on_inclusion_list )
2528 - [ Modified ` on_block ` ] ( #modified-on_block )
@@ -234,6 +237,13 @@ def get_proposer_head(store: Store, head_root: Root, slot: Slot) -> Root:
234237 # Check that the missing votes are assigned to the parent and not being hoarded.
235238 parent_strong = is_parent_strong(store, head_root)
236239
240+ # Re-org more aggressively if there is a proposer equivocation in the previous slot.
241+ proposer_equivocation = is_proposer_equivocation(store, head_root)
242+
243+ # [New in EIP7805]
244+ # Check that the head block is in the unsatisfied inclusion list blocks
245+ inclusion_list_unsatisfied = head_root in store.unsatisfied_inclusion_list_blocks
246+
237247 reorg_prerequisites = all (
238248 [
239249 shuffling_stable,
@@ -246,16 +256,39 @@ def get_proposer_head(store: Store, head_root: Root, slot: Slot) -> Root:
246256 ]
247257 )
248258
249- # [New in EIP7805]
250- # Check that the head block is in the unsatisfied inclusion list blocks
251- inclusion_list_unsatisfied = head_root in store.unsatisfied_inclusion_list_blocks
252-
253259 if reorg_prerequisites and (head_late or inclusion_list_unsatisfied):
254260 return parent_root
261+ elif all ([head_weak, current_time_ok, proposer_equivocation]):
262+ return parent_root
255263 else :
256264 return head_root
257265```
258266
267+ ## Updated fork-choice helpers
268+
269+ ### Modified ` update_proposer_boost_root `
270+
271+ ``` python
272+ def update_proposer_boost_root (store : Store, root : Root) -> None :
273+ is_first_block = store.proposer_boost_root == Root()
274+ is_timely = store.block_timeliness[root]
275+ is_inclusion_list_satisfied = root not in store.unsatisfied_inclusion_list_blocks
276+
277+ # [Modified in EIP7805]
278+ # Add proposer score boost if the block is timely, not conflicting with an
279+ # existing block, with the same the proposer as the canonical chain
280+ # and satisfies the inclusion list constraints.
281+ if is_timely and is_first_block and is_inclusion_list_satisfied:
282+ head_state = copy(store.block_states[get_head(store)])
283+ slot = get_current_slot(store)
284+ if head_state.slot < slot:
285+ process_slots(head_state, slot)
286+ block = store.blocks[root]
287+ # Only update if the proposer is the same as on the canonical chain
288+ if block.proposer_index == get_beacon_proposer_index(head_state):
289+ store.proposer_boost_root = root
290+ ```
291+
259292## New fork-choice helpers
260293
261294### New ` get_view_freeze_cutoff_ms `
@@ -279,6 +312,17 @@ def get_proposer_inclusion_list_cutoff_ms(epoch: Epoch) -> uint64:
279312 return get_slot_component_duration_ms(PROPOSER_INCLUSION_LIST_CUTOFF_BPS )
280313```
281314
315+ ### New ` record_block_inclusion_list_satisfaction `
316+
317+ ``` python
318+ def record_block_inclusion_list_satisfaction (store : Store, root : Root) -> None :
319+ # Check if block satisfies the inclusion list constraints
320+ # If not, add this block to the store as inclusion list constraints unsatisfied
321+ is_inclusion_list_satisfied = validate_inclusion_lists(store, root, EXECUTION_ENGINE )
322+ if not is_inclusion_list_satisfied:
323+ store.unsatisfied_inclusion_list_blocks.add(root)
324+ ```
325+
282326## Updated fork-choice handlers
283327
284328### New ` on_inclusion_list `
@@ -320,6 +364,8 @@ def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
320364 block = signed_block.message
321365 # Parent block must be known
322366 assert block.parent_root in store.block_states
367+ # Make a copy of the state to avoid mutability issues
368+ state = copy(store.block_states[block.parent_root])
323369 # Blocks cannot be in the future. If they are, their consideration must be delayed until they are in the past.
324370 assert get_current_slot(store) >= block.slot
325371
@@ -339,8 +385,6 @@ def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
339385 assert is_data_available(hash_tree_root(block))
340386
341387 # Check the block is valid and compute the post-state
342- # Make a copy of the state to avoid mutability issues
343- state = copy(store.block_states[block.parent_root])
344388 block_root = hash_tree_root(block)
345389 state_transition(state, signed_block, True )
346390
@@ -349,28 +393,10 @@ def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
349393 # Add new state for this block to the store
350394 store.block_states[block_root] = state
351395
352- # Add block timeliness to the store
353- seconds_since_genesis = store.time - store.genesis_time
354- time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS
355- epoch = get_current_store_epoch(store)
356- attestation_threshold_ms = get_attestation_due_ms(epoch)
357- is_before_attesting_interval = time_into_slot_ms < attestation_threshold_ms
358- is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval
359- store.block_timeliness[hash_tree_root(block)] = is_timely
360-
396+ record_block_timeliness(store, block_root)
361397 # [New in EIP7805]
362- # Check if block satisfies the inclusion list constraints
363- # If not, add this block to the store as inclusion list constraints unsatisfied
364- is_inclusion_list_satisfied = validate_inclusion_lists(store, block_root, EXECUTION_ENGINE )
365- if not is_inclusion_list_satisfied:
366- store.unsatisfied_inclusion_list_blocks.add(block_root)
367-
368- # Add proposer score boost if the block is timely, not conflicting with an existing block
369- # and satisfies the inclusion list constraints.
370- is_first_block = store.proposer_boost_root == Root()
371- # [Modified in EIP7805]
372- if is_timely and is_first_block and is_inclusion_list_satisfied:
373- store.proposer_boost_root = hash_tree_root(block)
398+ record_block_inclusion_list_satisfaction(store, block_root)
399+ update_proposer_boost_root(store, block_root)
374400
375401 # Update checkpoints in store if necessary
376402 update_checkpoints(store, state.current_justified_checkpoint, state.finalized_checkpoint)
0 commit comments