Skip to content
28 changes: 23 additions & 5 deletions crates/consensus/common/src/validation.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
//! Collection of methods for block validation.

use alloy_consensus::{
constants::MAXIMUM_EXTRA_DATA_SIZE, BlockHeader as _, Transaction, EMPTY_OMMER_ROOT_HASH,
};
use alloy_consensus::{BlockHeader as _, Transaction, EMPTY_OMMER_ROOT_HASH};
use alloy_eips::{eip4844::DATA_GAS_PER_BLOB, eip7840::BlobParams};
use reth_chainspec::{EthChainSpec, EthereumHardfork, EthereumHardforks};
use reth_consensus::{ConsensusError, TxGasLimitTooHighErr};
Expand Down Expand Up @@ -264,9 +262,12 @@ pub fn validate_4844_header_standalone<H: BlockHeader>(
/// 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_extra_data<H: BlockHeader>(header: &H) -> Result<(), ConsensusError> {
pub fn validate_header_extra_data<H: BlockHeader>(
header: &H,
max_size: usize,
) -> Result<(), ConsensusError> {
let extra_data_len = header.extra_data().len();
if extra_data_len > MAXIMUM_EXTRA_DATA_SIZE {
if extra_data_len > max_size {
Err(ConsensusError::ExtraDataExceedsMax { len: extra_data_len })
} else {
Ok(())
Expand Down Expand Up @@ -503,4 +504,21 @@ mod tests {
}))
);
}

#[test]
fn validate_header_extra_data_with_custom_limit() {
// Test with default 32 bytes - should pass
let header_32 = Header { extra_data: Bytes::from(vec![0; 32]), ..Default::default() };
assert!(validate_header_extra_data(&header_32, 32).is_ok());

// Test exceeding default - should fail
let header_33 = Header { extra_data: Bytes::from(vec![0; 33]), ..Default::default() };
assert_eq!(
validate_header_extra_data(&header_33, 32),
Err(ConsensusError::ExtraDataExceedsMax { len: 33 })
);

// Test with custom larger limit - should pass
assert!(validate_header_extra_data(&header_33, 64).is_ok());
}
}
19 changes: 16 additions & 3 deletions crates/ethereum/consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
extern crate alloc;

use alloc::{fmt::Debug, sync::Arc};
use alloy_consensus::EMPTY_OMMER_ROOT_HASH;
use alloy_consensus::{constants::MAXIMUM_EXTRA_DATA_SIZE, EMPTY_OMMER_ROOT_HASH};
use alloy_eips::eip7840::BlobParams;
use reth_chainspec::{EthChainSpec, EthereumHardforks};
use reth_consensus::{Consensus, ConsensusError, FullConsensus, HeaderValidator};
Expand All @@ -38,12 +38,25 @@ pub use validation::validate_block_post_execution;
pub struct EthBeaconConsensus<ChainSpec> {
/// Configuration
chain_spec: Arc<ChainSpec>,
/// Maximum allowed extra data size in bytes
max_extra_data_size: usize,
}

impl<ChainSpec: EthChainSpec + EthereumHardforks> EthBeaconConsensus<ChainSpec> {
/// Create a new instance of [`EthBeaconConsensus`]
pub const fn new(chain_spec: Arc<ChainSpec>) -> Self {
Self { chain_spec }
Self { chain_spec, max_extra_data_size: MAXIMUM_EXTRA_DATA_SIZE }
}

/// Returns the maximum allowed extra data size.
pub const fn max_extra_data_size(&self) -> usize {
self.max_extra_data_size
}

/// Sets the maximum allowed extra data size and returns the updated instance.
pub const fn with_max_extra_data_size(mut self, size: usize) -> Self {
self.max_extra_data_size = size;
self
}

/// Returns the chain spec associated with this consensus engine.
Expand Down Expand Up @@ -125,7 +138,7 @@ where
}
}
}
validate_header_extra_data(header)?;
validate_header_extra_data(header, self.max_extra_data_size)?;
validate_header_gas(header)?;
validate_header_base_fee(header, &self.chain_spec)?;

Expand Down
21 changes: 18 additions & 3 deletions crates/optimism/consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
extern crate alloc;

use alloc::{format, sync::Arc};
use alloy_consensus::{BlockHeader as _, EMPTY_OMMER_ROOT_HASH};
use alloy_consensus::{
constants::MAXIMUM_EXTRA_DATA_SIZE, BlockHeader as _, EMPTY_OMMER_ROOT_HASH,
};
use alloy_primitives::B64;
use core::fmt::Debug;
use reth_chainspec::EthChainSpec;
Expand Down Expand Up @@ -46,12 +48,25 @@ pub use error::OpConsensusError;
pub struct OpBeaconConsensus<ChainSpec> {
/// Configuration
chain_spec: Arc<ChainSpec>,
/// Maximum allowed extra data size in bytes
max_extra_data_size: usize,
}

impl<ChainSpec> OpBeaconConsensus<ChainSpec> {
/// Create a new instance of [`OpBeaconConsensus`]
pub const fn new(chain_spec: Arc<ChainSpec>) -> Self {
Self { chain_spec }
Self { chain_spec, max_extra_data_size: MAXIMUM_EXTRA_DATA_SIZE }
}

/// Returns the maximum allowed extra data size.
pub const fn max_extra_data_size(&self) -> usize {
self.max_extra_data_size
}

/// Sets the maximum allowed extra data size and returns the updated instance.
pub const fn with_max_extra_data_size(mut self, size: usize) -> Self {
self.max_extra_data_size = size;
self
}
}

Expand Down Expand Up @@ -166,7 +181,7 @@ where
// is greater than its parent timestamp.

// validate header extra data for all networks post merge
validate_header_extra_data(header)?;
validate_header_extra_data(header, self.max_extra_data_size)?;
validate_header_gas(header)?;
validate_header_base_fee(header, &self.chain_spec)
}
Expand Down