From cd5cf60deb83b654e847d00a60be31b5617154c2 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Mon, 18 Oct 2021 13:32:29 +0800 Subject: [PATCH] Clarify `get_pow_block` block-not-found case --- setup.py | 2 +- specs/merge/fork-choice.md | 12 +++++++++++- specs/merge/validator.md | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 3dcaaa44f..0611e5567 100644 --- a/setup.py +++ b/setup.py @@ -510,7 +510,7 @@ from eth2spec.utils.ssz.ssz_typing import Bytes20, ByteList, ByteVector, uint256 ExecutionState = Any -def get_pow_block(hash: Bytes32) -> PowBlock: +def get_pow_block(hash: Bytes32) -> Optional[PowBlock]: return PowBlock(block_hash=hash, parent_hash=Bytes32(), total_difficulty=uint256(0), difficulty=uint256(0)) diff --git a/specs/merge/fork-choice.md b/specs/merge/fork-choice.md index ea4a5588a..eb99cce64 100644 --- a/specs/merge/fork-choice.md +++ b/specs/merge/fork-choice.md @@ -64,7 +64,8 @@ class PowBlock(Container): ### `get_pow_block` -Let `get_pow_block(block_hash: Hash32) -> PowBlock` be the function that given the hash of the PoW block returns its data. +Let `get_pow_block(block_hash: Hash32) -> Optional[PowBlock]` be the function that given the hash of the PoW block returns its data. +It may result in `None` if the requested block is not found if execution engine is still syncing. *Note*: The `eth_getBlockByHash` JSON-RPC method may be used to pull this information from an execution client. @@ -90,6 +91,12 @@ def is_valid_terminal_pow_block(block: PowBlock, parent: PowBlock) -> bool: ```python def on_block(store: Store, signed_block: SignedBeaconBlock) -> None: + """ + Run ``on_block`` upon receiving a new block. + + An block that is asserted as invalid due to unavailable PoW block may be valid at a later time, + consider scheduling it for later processing in such case. + """ block = signed_block.message # Parent block must be known assert block.parent_root in store.block_states @@ -110,8 +117,11 @@ def on_block(store: Store, signed_block: SignedBeaconBlock) -> None: # [New in Merge] if is_merge_block(pre_state, block.body): + # Note: the unavailable PoW block(s) may be available later pow_block = get_pow_block(block.body.execution_payload.parent_hash) + assert pow_block is not None pow_parent = get_pow_block(pow_block.parent_hash) + assert pow_parent is not None assert is_valid_terminal_pow_block(pow_block, pow_parent) # Add new block to the store diff --git a/specs/merge/validator.md b/specs/merge/validator.md index 2de4ef6b1..9fd1a24f7 100644 --- a/specs/merge/validator.md +++ b/specs/merge/validator.md @@ -103,6 +103,7 @@ def get_pow_block_at_terminal_total_difficulty(pow_chain: Sequence[PowBlock]) -> # `pow_chain` abstractly represents all blocks in the PoW chain for block in pow_chain: parent = get_pow_block(block.parent_hash) + assert parent is not None block_reached_ttd = block.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY parent_reached_ttd = parent.total_difficulty >= TERMINAL_TOTAL_DIFFICULTY if block_reached_ttd and not parent_reached_ttd: