diff --git a/crates/primitives-traits/src/block/mod.rs b/crates/primitives-traits/src/block/mod.rs index 4c98a94b3..f161ced82 100644 --- a/crates/primitives-traits/src/block/mod.rs +++ b/crates/primitives-traits/src/block/mod.rs @@ -88,3 +88,29 @@ where (self.header, self.body) } } + +/// An extension trait for [`Block`]s that allows for mutable access to the block's internals. +/// +/// This allows for modifying the block's header and body for testing purposes. +#[cfg(any(test, feature = "test-utils"))] +pub trait TestBlock: Block { + /// Returns mutable reference to block body. + fn body_mut(&mut self) -> &mut Self::Body; + + /// Returns mutable reference to block header. + fn header_mut(&mut self) -> &mut Self::Header; +} + +#[cfg(any(test, feature = "test-utils"))] +impl TestBlock for alloy_consensus::Block +where + T: SignedTransaction, +{ + fn body_mut(&mut self) -> &mut Self::Body { + &mut self.body + } + + fn header_mut(&mut self) -> &mut Self::Header { + &mut self.header + } +} diff --git a/crates/primitives-traits/src/header/sealed.rs b/crates/primitives-traits/src/header/sealed.rs index ef8b5fde5..4291735a6 100644 --- a/crates/primitives-traits/src/header/sealed.rs +++ b/crates/primitives-traits/src/header/sealed.rs @@ -119,6 +119,24 @@ impl Decodable for SealedHeader { } } +impl From> for Sealed { + fn from(value: SealedHeader) -> Self { + Self::new_unchecked(value.header, value.hash) + } +} + +#[cfg(any(test, feature = "arbitrary"))] +impl<'a, H> arbitrary::Arbitrary<'a> for SealedHeader +where + H: for<'b> arbitrary::Arbitrary<'b> + Sealable, +{ + fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { + let header = H::arbitrary(u)?; + + Ok(Self::seal(header)) + } +} + #[cfg(any(test, feature = "test-utils"))] impl SealedHeader { /// Updates the block header. @@ -152,24 +170,6 @@ impl SealedHeader { } } -impl From> for Sealed { - fn from(value: SealedHeader) -> Self { - Self::new_unchecked(value.header, value.hash) - } -} - -#[cfg(any(test, feature = "arbitrary"))] -impl<'a, H> arbitrary::Arbitrary<'a> for SealedHeader -where - H: for<'b> arbitrary::Arbitrary<'b> + Sealable, -{ - fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { - let header = H::arbitrary(u)?; - - Ok(Self::seal(header)) - } -} - /// Bincode-compatible [`SealedHeader`] serde implementation. #[cfg(feature = "serde-bincode-compat")] pub(super) mod serde_bincode_compat { diff --git a/crates/primitives-traits/src/header/test_utils.rs b/crates/primitives-traits/src/header/test_utils.rs index 0e79f6cb4..58237fbca 100644 --- a/crates/primitives-traits/src/header/test_utils.rs +++ b/crates/primitives-traits/src/header/test_utils.rs @@ -1,10 +1,45 @@ -//! Test utilities to generate random valid headers. +//! Test utilities for the block header. use alloy_consensus::Header; -use alloy_primitives::B256; +use alloy_primitives::{BlockHash, BlockNumber, B256, U256}; use proptest::{arbitrary::any, prop_compose}; use proptest_arbitrary_interop::arb; +/// A helper trait for [`Header`]s that allows for mutable access to the headers values. +/// +/// This allows for modifying the header for testing purposes. +pub trait TestHeader { + /// Updates the parent block hash. + fn set_parent_hash(&mut self, hash: BlockHash); + + /// Updates the block number. + fn set_block_number(&mut self, number: BlockNumber); + + /// Updates the block state root. + fn set_state_root(&mut self, state_root: B256); + + /// Updates the block difficulty. + fn set_difficulty(&mut self, difficulty: U256); +} + +impl TestHeader for Header { + fn set_parent_hash(&mut self, hash: BlockHash) { + self.parent_hash = hash + } + + fn set_block_number(&mut self, number: BlockNumber) { + self.number = number; + } + + fn set_state_root(&mut self, state_root: B256) { + self.state_root = state_root; + } + + fn set_difficulty(&mut self, difficulty: U256) { + self.difficulty = difficulty; + } +} + /// Generates a header which is valid __with respect to past and future forks__. This means, for /// example, that if the withdrawals root is present, the base fee per gas is also present. /// diff --git a/crates/primitives-traits/src/lib.rs b/crates/primitives-traits/src/lib.rs index c5d9b710c..bad587e0f 100644 --- a/crates/primitives-traits/src/lib.rs +++ b/crates/primitives-traits/src/lib.rs @@ -74,8 +74,6 @@ pub mod sync; /// Common header types pub mod header; -#[cfg(any(test, feature = "arbitrary", feature = "test-utils"))] -pub use header::test_utils; pub use header::{Header, HeaderError, SealedHeader}; /// Bincode-compatible serde implementations for common abstracted types in Reth. @@ -135,3 +133,11 @@ pub trait MaybeSerdeBincodeCompat {} impl MaybeSerdeBincodeCompat for T where T: crate::serde_bincode_compat::SerdeBincodeCompat {} #[cfg(not(feature = "serde-bincode-compat"))] impl MaybeSerdeBincodeCompat for T {} + +/// Utilities for testing. +#[cfg(any(test, feature = "arbitrary", feature = "test-utils"))] +pub mod test_utils { + pub use crate::header::test_utils::{generate_valid_header, valid_header_strategy}; + #[cfg(feature = "test-utils")] + pub use crate::{block::TestBlock, header::test_utils::TestHeader}; +}