From 3af2afe99528750dc7465433c4248fd1435bf3e0 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Mon, 9 Dec 2024 19:26:32 +0100 Subject: [PATCH] chore: relax more consensus functions (#13236) --- crates/consensus/common/Cargo.toml | 4 +- crates/consensus/common/src/validation.rs | 70 +++++++++++++---------- crates/ethereum/consensus/src/lib.rs | 2 +- crates/optimism/consensus/src/lib.rs | 2 +- crates/primitives/src/block.rs | 62 +++++++++++--------- 5 files changed, 79 insertions(+), 61 deletions(-) diff --git a/crates/consensus/common/Cargo.toml b/crates/consensus/common/Cargo.toml index 272adbb929..a9a0c69ae5 100644 --- a/crates/consensus/common/Cargo.toml +++ b/crates/consensus/common/Cargo.toml @@ -13,8 +13,8 @@ workspace = true [dependencies] # reth reth-chainspec.workspace = true -reth-primitives.workspace = true reth-consensus.workspace = true +reth-primitives.workspace = true # ethereum alloy-primitives.workspace = true @@ -24,8 +24,8 @@ alloy-consensus.workspace = true alloy-eips.workspace = true [dev-dependencies] +alloy-consensus.workspace = true reth-storage-api.workspace = true rand.workspace = true mockall = "0.13" -alloy-consensus.workspace = true diff --git a/crates/consensus/common/src/validation.rs b/crates/consensus/common/src/validation.rs index 2c38fa2d6c..37b6138e5d 100644 --- a/crates/consensus/common/src/validation.rs +++ b/crates/consensus/common/src/validation.rs @@ -1,14 +1,14 @@ //! Collection of methods for block validation. -use alloy_consensus::{constants::MAXIMUM_EXTRA_DATA_SIZE, BlockHeader}; +use alloy_consensus::{constants::MAXIMUM_EXTRA_DATA_SIZE, BlockHeader, EMPTY_OMMER_ROOT_HASH}; use alloy_eips::{ calc_next_block_base_fee, eip4844::{DATA_GAS_PER_BLOB, MAX_DATA_GAS_PER_BLOCK}, }; -use reth_chainspec::{EthChainSpec, EthereumHardforks}; +use reth_chainspec::{EthChainSpec, EthereumHardfork, EthereumHardforks}; use reth_consensus::ConsensusError; -use reth_primitives::{BlockBody, EthereumHardfork, GotExpected, SealedBlock, SealedHeader}; -use reth_primitives_traits::BlockBody as _; +use reth_primitives::SealedBlock; +use reth_primitives_traits::{BlockBody, GotExpected, SealedHeader}; use revm_primitives::calc_excess_blob_gas; /// Gas used needs to be less than gas limit. Gas used is going to be checked after execution. @@ -43,11 +43,11 @@ pub fn validate_header_base_fee( /// /// [EIP-4895]: https://eips.ethereum.org/EIPS/eip-4895 #[inline] -pub fn validate_shanghai_withdrawals( +pub fn validate_shanghai_withdrawals( block: &SealedBlock, ) -> Result<(), ConsensusError> { let withdrawals = block.body.withdrawals().ok_or(ConsensusError::BodyWithdrawalsMissing)?; - let withdrawals_root = reth_primitives::proofs::calculate_withdrawals_root(withdrawals); + let withdrawals_root = alloy_consensus::proofs::calculate_withdrawals_root(withdrawals); let header_withdrawals_root = block.withdrawals_root().ok_or(ConsensusError::WithdrawalsRootMissing)?; if withdrawals_root != *header_withdrawals_root { @@ -64,7 +64,7 @@ pub fn validate_shanghai_withdrawals( +pub fn validate_cancun_gas( block: &SealedBlock, ) -> Result<(), ConsensusError> { // Check that the blob gas used in the header matches the sum of the blob gas used by each @@ -87,28 +87,31 @@ pub fn validate_cancun_gas /// - ommer hash /// - transaction root /// - withdrawals root -pub fn validate_body_against_header( - body: &BlockBody, - header: &SealedHeader, -) -> Result<(), ConsensusError> { +pub fn validate_body_against_header(body: &B, header: &H) -> Result<(), ConsensusError> +where + B: BlockBody, + H: BlockHeader, +{ let ommers_hash = body.calculate_ommers_root(); - if header.ommers_hash != ommers_hash { + if Some(header.ommers_hash()) != ommers_hash { return Err(ConsensusError::BodyOmmersHashDiff( - GotExpected { got: ommers_hash, expected: header.ommers_hash }.into(), + GotExpected { + got: ommers_hash.unwrap_or(EMPTY_OMMER_ROOT_HASH), + expected: header.ommers_hash(), + } + .into(), )) } let tx_root = body.calculate_tx_root(); - if header.transactions_root != tx_root { + if header.transactions_root() != tx_root { return Err(ConsensusError::BodyTransactionRootDiff( - GotExpected { got: tx_root, expected: header.transactions_root }.into(), + GotExpected { got: tx_root, expected: header.transactions_root() }.into(), )) } - match (header.withdrawals_root, &body.withdrawals) { - (Some(header_withdrawals_root), Some(withdrawals)) => { - let withdrawals = withdrawals.as_slice(); - let withdrawals_root = reth_primitives::proofs::calculate_withdrawals_root(withdrawals); + match (header.withdrawals_root(), body.calculate_withdrawals_root()) { + (Some(header_withdrawals_root), Some(withdrawals_root)) => { if withdrawals_root != header_withdrawals_root { return Err(ConsensusError::BodyWithdrawalsRootDiff( GotExpected { got: withdrawals_root, expected: header_withdrawals_root }.into(), @@ -130,15 +133,24 @@ pub fn validate_body_against_header( /// - Compares the transactions root in the block header to the block body /// - Pre-execution transaction validation /// - (Optionally) Compares the receipts root in the block header to the block body -pub fn validate_block_pre_execution( - block: &SealedBlock, +pub fn validate_block_pre_execution( + block: &SealedBlock, chain_spec: &ChainSpec, -) -> Result<(), ConsensusError> { +) -> Result<(), ConsensusError> +where + H: BlockHeader, + B: BlockBody, + ChainSpec: EthereumHardforks, +{ // Check ommers hash let ommers_hash = block.body.calculate_ommers_root(); - if block.header.ommers_hash != ommers_hash { + if Some(block.header.ommers_hash()) != ommers_hash { return Err(ConsensusError::BodyOmmersHashDiff( - GotExpected { got: ommers_hash, expected: block.header.ommers_hash }.into(), + GotExpected { + got: ommers_hash.unwrap_or(EMPTY_OMMER_ROOT_HASH), + expected: block.header.ommers_hash(), + } + .into(), )) } @@ -148,11 +160,11 @@ pub fn validate_block_pre_execution( } // EIP-4895: Beacon chain push withdrawals as operations - if chain_spec.is_shanghai_active_at_timestamp(block.timestamp) { + if chain_spec.is_shanghai_active_at_timestamp(block.timestamp()) { validate_shanghai_withdrawals(block)?; } - if chain_spec.is_cancun_active_at_timestamp(block.timestamp) { + if chain_spec.is_cancun_active_at_timestamp(block.timestamp()) { validate_cancun_gas(block)?; } @@ -222,12 +234,12 @@ pub fn validate_header_extradata(header: &H) -> Result<(), Conse #[inline] pub fn validate_against_parent_hash_number( header: &H, - parent: &SealedHeader, + parent: &SealedHeader, ) -> Result<(), ConsensusError> { // Parent number is consistent. - if parent.number + 1 != header.number() { + if parent.number() + 1 != header.number() { return Err(ConsensusError::ParentBlockNumberMismatch { - parent_block_number: parent.number, + parent_block_number: parent.number(), block_number: header.number(), }) } diff --git a/crates/ethereum/consensus/src/lib.rs b/crates/ethereum/consensus/src/lib.rs index ba737e5672..4d3ba62826 100644 --- a/crates/ethereum/consensus/src/lib.rs +++ b/crates/ethereum/consensus/src/lib.rs @@ -121,7 +121,7 @@ impl Consensu body: &BlockBody, header: &SealedHeader, ) -> Result<(), ConsensusError> { - validate_body_against_header(body, header) + validate_body_against_header(body, header.header()) } fn validate_block_pre_execution(&self, block: &SealedBlock) -> Result<(), ConsensusError> { diff --git a/crates/optimism/consensus/src/lib.rs b/crates/optimism/consensus/src/lib.rs index 6d457f42c9..d05ff9c9bd 100644 --- a/crates/optimism/consensus/src/lib.rs +++ b/crates/optimism/consensus/src/lib.rs @@ -65,7 +65,7 @@ impl Consensus for OpBeaconConsensus { body: &BlockBody, header: &SealedHeader, ) -> Result<(), ConsensusError> { - validate_body_against_header(body, header) + validate_body_against_header(body, header.header()) } fn validate_block_pre_execution(&self, block: &SealedBlock) -> Result<(), ConsensusError> { diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs index 799e3e7a4c..b02456f6c4 100644 --- a/crates/primitives/src/block.rs +++ b/crates/primitives/src/block.rs @@ -296,6 +296,40 @@ impl SealedBlock { } } +impl SealedBlock +where + H: alloy_consensus::BlockHeader, + B: reth_primitives_traits::BlockBody, +{ + /// Ensures that the transaction root in the block header is valid. + /// + /// The transaction root is the Keccak 256-bit hash of the root node of the trie structure + /// populated with each transaction in the transactions list portion of the block. + /// + /// # Returns + /// + /// Returns `Ok(())` if the calculated transaction root matches the one stored in the header, + /// indicating that the transactions in the block are correctly represented in the trie. + /// + /// Returns `Err(error)` if the transaction root validation fails, providing a `GotExpected` + /// error containing the calculated and expected roots. + pub fn ensure_transaction_root_valid(&self) -> Result<(), GotExpected> + where + B::Transaction: Encodable2718, + { + let calculated_root = self.body.calculate_tx_root(); + + if self.header.transactions_root() != calculated_root { + return Err(GotExpected { + got: calculated_root, + expected: self.header.transactions_root(), + }) + } + + Ok(()) + } +} + impl SealedBlock where H: reth_primitives_traits::BlockHeader, @@ -385,34 +419,6 @@ where Block::new(self.header.unseal(), self.body) } - /// Ensures that the transaction root in the block header is valid. - /// - /// The transaction root is the Keccak 256-bit hash of the root node of the trie structure - /// populated with each transaction in the transactions list portion of the block. - /// - /// # Returns - /// - /// Returns `Ok(())` if the calculated transaction root matches the one stored in the header, - /// indicating that the transactions in the block are correctly represented in the trie. - /// - /// Returns `Err(error)` if the transaction root validation fails, providing a `GotExpected` - /// error containing the calculated and expected roots. - pub fn ensure_transaction_root_valid(&self) -> Result<(), GotExpected> - where - B::Transaction: Encodable2718, - { - let calculated_root = self.body.calculate_tx_root(); - - if self.header.transactions_root() != calculated_root { - return Err(GotExpected { - got: calculated_root, - expected: self.header.transactions_root(), - }) - } - - Ok(()) - } - /// Returns a vector of encoded 2718 transactions. /// /// This is also known as `raw transactions`.