diff --git a/crates/consensus/common/src/validation.rs b/crates/consensus/common/src/validation.rs index b5314cdd1..9e7f8d451 100644 --- a/crates/consensus/common/src/validation.rs +++ b/crates/consensus/common/src/validation.rs @@ -1,7 +1,10 @@ //! Collection of methods for block validation. -use alloy_consensus::{constants::MAXIMUM_EXTRA_DATA_SIZE, BlockHeader, Header}; -use alloy_eips::eip4844::{DATA_GAS_PER_BLOB, MAX_DATA_GAS_PER_BLOCK}; +use alloy_consensus::{constants::MAXIMUM_EXTRA_DATA_SIZE, BlockHeader}; +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_consensus::ConsensusError; use reth_primitives::{ @@ -162,11 +165,11 @@ pub fn validate_block_pre_execution( /// * `blob_gas_used` is less than or equal to `MAX_DATA_GAS_PER_BLOCK` /// * `blob_gas_used` is a multiple of `DATA_GAS_PER_BLOB` /// * `excess_blob_gas` is a multiple of `DATA_GAS_PER_BLOB` -pub fn validate_4844_header_standalone(header: &Header) -> Result<(), ConsensusError> { - let blob_gas_used = header.blob_gas_used.ok_or(ConsensusError::BlobGasUsedMissing)?; - let excess_blob_gas = header.excess_blob_gas.ok_or(ConsensusError::ExcessBlobGasMissing)?; +pub fn validate_4844_header_standalone(header: &H) -> Result<(), ConsensusError> { + let blob_gas_used = header.blob_gas_used().ok_or(ConsensusError::BlobGasUsedMissing)?; + let excess_blob_gas = header.excess_blob_gas().ok_or(ConsensusError::ExcessBlobGasMissing)?; - if header.parent_beacon_block_root.is_none() { + if header.parent_beacon_block_root().is_none() { return Err(ConsensusError::ParentBeaconBlockRootMissing) } @@ -201,8 +204,8 @@ pub fn validate_4844_header_standalone(header: &Header) -> Result<(), ConsensusE /// From yellow paper: extraData: An arbitrary byte array containing data relevant to this block. /// This must be 32 bytes or fewer; formally Hx. #[inline] -pub fn validate_header_extradata(header: &Header) -> Result<(), ConsensusError> { - let extradata_len = header.extra_data.len(); +pub fn validate_header_extradata(header: &H) -> Result<(), ConsensusError> { + let extradata_len = header.extra_data().len(); if extradata_len > MAXIMUM_EXTRA_DATA_SIZE { Err(ConsensusError::ExtraDataExceedsMax { len: extradata_len }) } else { @@ -215,21 +218,21 @@ pub fn validate_header_extradata(header: &Header) -> Result<(), ConsensusError> /// This function ensures that the header block number is sequential and that the hash of the parent /// header matches the parent hash in the header. #[inline] -pub fn validate_against_parent_hash_number( - header: &Header, +pub fn validate_against_parent_hash_number( + header: &H, 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, - block_number: header.number, + block_number: header.number(), }) } - if parent.hash() != header.parent_hash { + if parent.hash() != header.parent_hash() { return Err(ConsensusError::ParentHashMismatch( - GotExpected { got: header.parent_hash, expected: parent.hash() }.into(), + GotExpected { got: header.parent_hash(), expected: parent.hash() }.into(), )) } @@ -238,23 +241,30 @@ pub fn validate_against_parent_hash_number( /// Validates the base fee against the parent and EIP-1559 rules. #[inline] -pub fn validate_against_parent_eip1559_base_fee( - header: &Header, - parent: &Header, +pub fn validate_against_parent_eip1559_base_fee< + H: BlockHeader, + ChainSpec: EthChainSpec + EthereumHardforks, +>( + header: &H, + parent: &H, chain_spec: &ChainSpec, ) -> Result<(), ConsensusError> { - if chain_spec.fork(EthereumHardfork::London).active_at_block(header.number) { - let base_fee = header.base_fee_per_gas.ok_or(ConsensusError::BaseFeeMissing)?; + if chain_spec.fork(EthereumHardfork::London).active_at_block(header.number()) { + let base_fee = header.base_fee_per_gas().ok_or(ConsensusError::BaseFeeMissing)?; let expected_base_fee = - if chain_spec.fork(EthereumHardfork::London).transitions_at_block(header.number) { + if chain_spec.fork(EthereumHardfork::London).transitions_at_block(header.number()) { alloy_eips::eip1559::INITIAL_BASE_FEE } else { // This BaseFeeMissing will not happen as previous blocks are checked to have // them. - parent - .next_block_base_fee(chain_spec.base_fee_params_at_timestamp(header.timestamp)) - .ok_or(ConsensusError::BaseFeeMissing)? + let base_fee = parent.base_fee_per_gas().ok_or(ConsensusError::BaseFeeMissing)?; + calc_next_block_base_fee( + parent.gas_used(), + parent.gas_limit(), + base_fee, + chain_spec.base_fee_params_at_timestamp(header.timestamp()), + ) }; if expected_base_fee != base_fee { return Err(ConsensusError::BaseFeeDiff(GotExpected { @@ -269,14 +279,14 @@ pub fn validate_against_parent_eip1559_base_fee( + header: &H, + parent: &H, ) -> Result<(), ConsensusError> { - if header.timestamp <= parent.timestamp { + if header.timestamp() <= parent.timestamp() { return Err(ConsensusError::TimestampIsInPast { - parent_timestamp: parent.timestamp, - timestamp: header.timestamp, + parent_timestamp: parent.timestamp(), + timestamp: header.timestamp(), }) } Ok(()) @@ -286,9 +296,9 @@ pub const fn validate_against_parent_timestamp( /// ensures that the `blob_gas_used` and `excess_blob_gas` fields exist in the child header, and /// that the `excess_blob_gas` field matches the expected `excess_blob_gas` calculated from the /// parent header fields. -pub fn validate_against_parent_4844( - header: &Header, - parent: &Header, +pub fn validate_against_parent_4844( + header: &H, + parent: &H, ) -> Result<(), ConsensusError> { // From [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844#header-extension): // @@ -296,13 +306,13 @@ pub fn validate_against_parent_4844( // > are evaluated as 0. // // This means in the first post-fork block, calc_excess_blob_gas will return 0. - let parent_blob_gas_used = parent.blob_gas_used.unwrap_or(0); - let parent_excess_blob_gas = parent.excess_blob_gas.unwrap_or(0); + let parent_blob_gas_used = parent.blob_gas_used().unwrap_or(0); + let parent_excess_blob_gas = parent.excess_blob_gas().unwrap_or(0); - if header.blob_gas_used.is_none() { + if header.blob_gas_used().is_none() { return Err(ConsensusError::BlobGasUsedMissing) } - let excess_blob_gas = header.excess_blob_gas.ok_or(ConsensusError::ExcessBlobGasMissing)?; + let excess_blob_gas = header.excess_blob_gas().ok_or(ConsensusError::ExcessBlobGasMissing)?; let expected_excess_blob_gas = calc_excess_blob_gas(parent_excess_blob_gas, parent_blob_gas_used); @@ -320,7 +330,7 @@ pub fn validate_against_parent_4844( #[cfg(test)] mod tests { use super::*; - use alloy_consensus::{TxEip4844, EMPTY_OMMER_ROOT_HASH, EMPTY_ROOT_HASH}; + use alloy_consensus::{Header, TxEip4844, EMPTY_OMMER_ROOT_HASH, EMPTY_ROOT_HASH}; use alloy_eips::{ eip4895::{Withdrawal, Withdrawals}, BlockHashOrNumber, diff --git a/crates/ethereum/consensus/src/lib.rs b/crates/ethereum/consensus/src/lib.rs index 2c260c4a7..96dfbae3f 100644 --- a/crates/ethereum/consensus/src/lib.rs +++ b/crates/ethereum/consensus/src/lib.rs @@ -134,7 +134,7 @@ impl HeaderVa // Ensures that EIP-4844 fields are valid once cancun is active. if self.chain_spec.is_cancun_active_at_timestamp(header.timestamp) { - validate_4844_header_standalone(header)?; + validate_4844_header_standalone(header.header())?; } else if header.blob_gas_used.is_some() { return Err(ConsensusError::BlobGasUsedUnexpected) } else if header.excess_blob_gas.is_some() { @@ -159,19 +159,23 @@ impl HeaderVa header: &SealedHeader, parent: &SealedHeader, ) -> Result<(), ConsensusError> { - validate_against_parent_hash_number(header, parent)?; + validate_against_parent_hash_number(header.header(), parent)?; - validate_against_parent_timestamp(header, parent)?; + validate_against_parent_timestamp(header.header(), parent.header())?; // TODO Check difficulty increment between parent and self // Ace age did increment it by some formula that we need to follow. self.validate_against_parent_gas_limit(header, parent)?; - validate_against_parent_eip1559_base_fee(header, parent, &self.chain_spec)?; + validate_against_parent_eip1559_base_fee( + header.header(), + parent.header(), + &self.chain_spec, + )?; // ensure that the blob gas fields for this block if self.chain_spec.is_cancun_active_at_timestamp(header.timestamp) { - validate_against_parent_4844(header, parent)?; + validate_against_parent_4844(header.header(), parent.header())?; } Ok(()) diff --git a/crates/optimism/consensus/src/lib.rs b/crates/optimism/consensus/src/lib.rs index 69d943785..cb357db92 100644 --- a/crates/optimism/consensus/src/lib.rs +++ b/crates/optimism/consensus/src/lib.rs @@ -101,17 +101,21 @@ impl HeaderValidator for OpBeaconConsensus { header: &SealedHeader, parent: &SealedHeader, ) -> Result<(), ConsensusError> { - validate_against_parent_hash_number(header, parent)?; + validate_against_parent_hash_number(header.header(), parent)?; if self.chain_spec.is_bedrock_active_at_block(header.number) { - validate_against_parent_timestamp(header, parent)?; + validate_against_parent_timestamp(header.header(), parent.header())?; } - validate_against_parent_eip1559_base_fee(header, parent, &self.chain_spec)?; + validate_against_parent_eip1559_base_fee( + header.header(), + parent.header(), + &self.chain_spec, + )?; // ensure that the blob gas fields for this block if self.chain_spec.is_cancun_active_at_timestamp(header.timestamp) { - validate_against_parent_4844(header, parent)?; + validate_against_parent_4844(header.header(), parent.header())?; } Ok(())