diff --git a/beacon_chain/gossip_processing/gossip_validation.nim b/beacon_chain/gossip_processing/gossip_validation.nim index 25a0f08e81..3b44c4fe28 100644 --- a/beacon_chain/gossip_processing/gossip_validation.nim +++ b/beacon_chain/gossip_processing/gossip_validation.nim @@ -306,8 +306,7 @@ func getMaxBlobsPerBlock(cfg: RuntimeConfig, slot: Slot): uint64 = else: cfg.MAX_BLOBS_PER_BLOCK -debugGloasComment "" -# https://github.com/ethereum/consensus-specs/blob/v1.6.0-beta.0/specs/gloas/p2p-interface.md#beacon_block +# https://github.com/ethereum/consensus-specs/blob/v1.6.0-beta.1/specs/gloas/p2p-interface.md#beacon_block template validateBeaconBlockBellatrix( _: phase0.SignedBeaconBlock | altair.SignedBeaconBlock | gloas.SignedBeaconBlock, _: BlockRef): untyped = @@ -367,8 +366,7 @@ template validateBeaconBlockBellatrix( # cannot occur here, because Nimbus's optimistic sync waits for either # `ACCEPTED` or `SYNCING` from the EL to get this far. -debugGloasComment "" -# https://github.com/ethereum/consensus-specs/blob/v1.6.0-beta.0/specs/gloas/p2p-interface.md#beacon_block +# https://github.com/ethereum/consensus-specs/blob/v1.6.0-beta.1/specs/gloas/p2p-interface.md#beacon_block template validateBeaconBlockDeneb( _: ChainDAGRef, _: @@ -394,6 +392,51 @@ template validateBeaconBlockDeneb( blob_params.MAX_BLOBS_PER_BLOCK): return dag.checkedReject("validateBeaconBlockDeneb: too many blob commitments") +template validateBeaconBlockGloas( + _: ChainDAGRef, + _: + phase0.SignedBeaconBlock | altair.SignedBeaconBlock | + bellatrix.SignedBeaconBlock | capella.SignedBeaconBlock | + deneb.SignedBeaconBlock | electra.SignedBeaconBlock | + fulu.SignedBeaconBlock, + _: BlockRef): untyped = + discard + +# https://github.com/ethereum/consensus-specs/blob/v1.6.0-beta.1/specs/gloas/p2p-interface.md#beacon_block +template validateBeaconBlockGloas( + dag: ChainDAGRef, + signed_beacon_block: gloas.SignedBeaconBlock, + parent: BlockRef): untyped = + template blck: untyped = signed_beacon_block.message + template bid: untyped = blck.body.signed_execution_payload_bid.message + + # If `execution_payload` verification of block's execution payload parent by + # an execution node **is complete** + debugGloasComment("") + let isExecutionEnabled = + if signed_beacon_block.message.is_execution_block: + true + else: + # If we don't know whether the parent block had execution enabled, + # assume it didn't. This way, we don't reject here if the timestamp + # is invalid, and let state transition check the timestamp. + # This is an edge case, and may be hit in a pathological scenario with + # checkpoint sync, because the checkpoint block may be unavailable + # and it could already be the parent of the new block before backfill. + not dag.loadExecutionBlockHash(parent).get(ZERO_HASH).isZero + if isExecutionEnabled: + # [REJECT] The block's execution payload parent (defined by + # `bid.parent_block_hash`) passes all validation. + withState(dag.headState): + when consensusFork >= ConsensusFork.Gloas: + if bid.parent_block_hash != forkyState.data.latest_block_hash: + return dag.checkedReject("validateBeaconBlockGloas: invalid execution payload parent") + + # [REJECT] The bid's parent (defined by `bid.parent_block_root`) equals the + # block's parent (defined by `block.parent_root`). + if bid.parent_block_root != blck.parent_root: + return dag.checkedReject("validateBeaconBlockGloas: parent block root mismatch") + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/deneb/p2p-interface.md#blob_sidecar_subnet_id proc validateBlobSidecar*( dag: ChainDAGRef, quarantine: ref Quarantine, @@ -779,6 +822,7 @@ proc validateDataColumnSidecar*( # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/phase0/p2p-interface.md#beacon_block # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/bellatrix/p2p-interface.md#beacon_block +# https://github.com/ethereum/consensus-specs/blob/v1.6.0-beta.1/specs/gloas/p2p-interface.md#beacon_block proc validateBeaconBlock*( dag: ChainDAGRef, quarantine: ref Quarantine, signed_beacon_block: ForkySignedBeaconBlock, @@ -857,43 +901,58 @@ proc validateBeaconBlock*( if signed_beacon_block.message.parent_root in quarantine[].unviable: quarantine[].addUnviable(signed_beacon_block.root) - # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/bellatrix/p2p-interface.md#beacon_block - # `is_execution_enabled(state, block.body)` check, but unlike in - # validateBeaconBlockBellatrix() don't have parent BlockRef. - if signed_beacon_block.message.is_execution_block: - # Blocks with execution enabled will be permitted to propagate - # regardless of the validity of the execution payload. This prevents - # network segregation between optimistic and non-optimistic nodes. - # - # If execution_payload verification of block's parent by an execution - # node is not complete: - # - # - [REJECT] The block's parent (defined by `block.parent_root`) passes - # all validation (excluding execution node verification of the - # `block.body.execution_payload`). - # - # otherwise: - # - # - [IGNORE] The block's parent (defined by `block.parent_root`) passes - # all validation (including execution node verification of the - # `block.body.execution_payload`). - - # Implementation restrictions: - # - # - We don't know if the parent state had execution enabled. - # If it had, and the block doesn't have it enabled anymore, - # we end up in the pre-Merge path below (`else`) and REJECT. - # Such a block is clearly invalid, though, without asking the EL. - # - # - We know that the parent was marked unviable, but don't know - # whether it was marked unviable due to consensus (REJECT) or - # execution (IGNORE) verification failure. We err on the IGNORE side. - return errIgnore("BeaconBlock: ignored, parent from unviable fork") + when type(signed_beacon_block).kind >= ConsensusFork.Gloas: + # https://github.com/ethereum/consensus-specs/blob/v1.6.0-beta.1/specs/gloas/p2p-interface.md#beacon_block + # some validations removed so we only need to check + if signed_beacon_block.message.is_execution_block: + # - [REJECT] The block's parent (defined by `block.parent_root`) passes + # all validation (excluding execution node verification of the + # `block.body.execution_payload`). + # + # otherwise: + # + # - [IGNORE] The block's parent (defined by `block.parent_root`) passes + # all validation (including execution node verification of the + # `block.body.execution_payload`). + return errIgnore("BeaconBlock: ignored, parent from unviable fork") else: - # [REJECT] The block's parent (defined by `block.parent_root`) passes - # validation. - return dag.checkedReject( - "BeaconBlock: rejected, parent from unviable fork") + # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/bellatrix/p2p-interface.md#beacon_block + # `is_execution_enabled(state, block.body)` check, but unlike in + # validateBeaconBlockBellatrix() don't have parent BlockRef. + if signed_beacon_block.message.is_execution_block: + # Blocks with execution enabled will be permitted to propagate + # regardless of the validity of the execution payload. This prevents + # network segregation between optimistic and non-optimistic nodes. + # + # If execution_payload verification of block's parent by an execution + # node is not complete: + # + # - [REJECT] The block's parent (defined by `block.parent_root`) passes + # all validation (excluding execution node verification of the + # `block.body.execution_payload`). + # + # otherwise: + # + # - [IGNORE] The block's parent (defined by `block.parent_root`) passes + # all validation (including execution node verification of the + # `block.body.execution_payload`). + + # Implementation restrictions: + # + # - We don't know if the parent state had execution enabled. + # If it had, and the block doesn't have it enabled anymore, + # we end up in the pre-Merge path below (`else`) and REJECT. + # Such a block is clearly invalid, though, without asking the EL. + # + # - We know that the parent was marked unviable, but don't know + # whether it was marked unviable due to consensus (REJECT) or + # execution (IGNORE) verification failure. We err on the IGNORE side. + return errIgnore("BeaconBlock: ignored, parent from unviable fork") + else: + # [REJECT] The block's parent (defined by `block.parent_root`) passes + # validation. + return dag.checkedReject( + "BeaconBlock: rejected, parent from unviable fork") # When the parent is missing, we can't validate the block - we'll queue it # in the quarantine for later processing @@ -918,6 +977,8 @@ proc validateBeaconBlock*( dag.validateBeaconBlockDeneb(signed_beacon_block, wallTime) + dag.validateBeaconBlockGloas(signed_beacon_block, parent) + # [REJECT] The block is from a higher slot than its parent. if not (signed_beacon_block.message.slot > parent.bid.slot): return dag.checkedReject(