feat: generalize Block impls (#14133)

This commit is contained in:
Arsenii Kulikov
2025-02-01 02:05:09 +04:00
committed by GitHub
parent 1c9ef8c5a3
commit a39980a6f6
12 changed files with 49 additions and 39 deletions

View File

@ -64,7 +64,7 @@ async fn test_get_body() {
for _ in 0..100 { for _ in 0..100 {
// Set a new random block to the mock storage and request it via the network // Set a new random block to the mock storage and request it via the network
let block_hash = rng.gen(); let block_hash = rng.gen();
let mut block = Block::default(); let mut block: Block = Block::default();
block.body.transactions.push(rng_transaction(&mut rng)); block.body.transactions.push(rng_transaction(&mut rng));
mock_provider.add_block(block_hash, block.clone()); mock_provider.add_block(block_hash, block.clone());

View File

@ -352,7 +352,7 @@ mod tests {
const TX: [u8; 251] = hex!("7ef8f8a0a539eb753df3b13b7e386e147d45822b67cb908c9ddc5618e3dbaa22ed00850b94deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8a4440a5e2000000558000c5fc50000000000000000000000006605a89f00000000012a10d90000000000000000000000000000000000000000000000000000000af39ac3270000000000000000000000000000000000000000000000000000000d5ea528d24e582fa68786f080069bdbfe06a43f8e67bfd31b8e4d8a8837ba41da9a82a54a0000000000000000000000006887246668a3b87f54deb3b94ba47a6f63f32985"); const TX: [u8; 251] = hex!("7ef8f8a0a539eb753df3b13b7e386e147d45822b67cb908c9ddc5618e3dbaa22ed00850b94deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8a4440a5e2000000558000c5fc50000000000000000000000006605a89f00000000012a10d90000000000000000000000000000000000000000000000000000000af39ac3270000000000000000000000000000000000000000000000000000000d5ea528d24e582fa68786f080069bdbfe06a43f8e67bfd31b8e4d8a8837ba41da9a82a54a0000000000000000000000006887246668a3b87f54deb3b94ba47a6f63f32985");
let tx = OpTransactionSigned::decode_2718(&mut TX.as_slice()).unwrap(); let tx = OpTransactionSigned::decode_2718(&mut TX.as_slice()).unwrap();
let block = Block { let block: Block<OpTransactionSigned> = Block {
body: BlockBody { transactions: vec![tx], ..Default::default() }, body: BlockBody { transactions: vec![tx], ..Default::default() },
..Default::default() ..Default::default()
}; };

View File

@ -293,7 +293,7 @@ mod test {
OpTransactionSigned::decode_2718(&mut TX_1_OP_MAINNET_BLOCK_124665056.as_slice()) OpTransactionSigned::decode_2718(&mut TX_1_OP_MAINNET_BLOCK_124665056.as_slice())
.unwrap(); .unwrap();
let block = Block { let block: Block<OpTransactionSigned> = Block {
body: BlockBody { transactions: [tx_0, tx_1.clone()].to_vec(), ..Default::default() }, body: BlockBody { transactions: [tx_0, tx_1.clone()].to_vec(), ..Default::default() },
..Default::default() ..Default::default()
}; };
@ -359,7 +359,7 @@ mod test {
let system = hex!("7ef8f8a0389e292420bcbf9330741f72074e39562a09ff5a00fd22e4e9eee7e34b81bca494deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8a4440a5e20000008dd00101c120000000000000004000000006721035b00000000014189960000000000000000000000000000000000000000000000000000000349b4dcdc000000000000000000000000000000000000000000000000000000004ef9325cc5991ce750960f636ca2ffbb6e209bb3ba91412f21dd78c14ff154d1930f1f9a0000000000000000000000005050f69a9786f081509234f1a7f4684b5e5b76c9"); let system = hex!("7ef8f8a0389e292420bcbf9330741f72074e39562a09ff5a00fd22e4e9eee7e34b81bca494deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8a4440a5e20000008dd00101c120000000000000004000000006721035b00000000014189960000000000000000000000000000000000000000000000000000000349b4dcdc000000000000000000000000000000000000000000000000000000004ef9325cc5991ce750960f636ca2ffbb6e209bb3ba91412f21dd78c14ff154d1930f1f9a0000000000000000000000005050f69a9786f081509234f1a7f4684b5e5b76c9");
let tx_0 = OpTransactionSigned::decode_2718(&mut &system[..]).unwrap(); let tx_0 = OpTransactionSigned::decode_2718(&mut &system[..]).unwrap();
let block = Block { let block: alloy_consensus::Block<OpTransactionSigned> = Block {
body: BlockBody { transactions: vec![tx_0], ..Default::default() }, body: BlockBody { transactions: vec![tx_0], ..Default::default() },
..Default::default() ..Default::default()
}; };

View File

@ -88,7 +88,7 @@ impl PayloadJob for TestPayloadJob {
fn best_payload(&self) -> Result<EthBuiltPayload, PayloadBuilderError> { fn best_payload(&self) -> Result<EthBuiltPayload, PayloadBuilderError> {
Ok(EthBuiltPayload::new( Ok(EthBuiltPayload::new(
self.attr.payload_id(), self.attr.payload_id(),
Arc::new(Block::default().seal_slow()), Arc::new(Block::<_>::default().seal_slow()),
U256::ZERO, U256::ZERO,
Some(Default::default()), Some(Default::default()),
)) ))

View File

@ -5,7 +5,7 @@ use crate::{
MaybeSerdeBincodeCompat, SignedTransaction, MaybeSerdeBincodeCompat, SignedTransaction,
}; };
use alloc::{fmt, vec::Vec}; use alloc::{fmt, vec::Vec};
use alloy_consensus::{Header, Transaction, Typed2718}; use alloy_consensus::{Transaction, Typed2718};
use alloy_eips::{eip2718::Encodable2718, eip4895::Withdrawals}; use alloy_eips::{eip2718::Encodable2718, eip4895::Withdrawals};
use alloy_primitives::{Address, Bytes, B256}; use alloy_primitives::{Address, Bytes, B256};
@ -177,12 +177,13 @@ pub trait BlockBody:
} }
} }
impl<T> BlockBody for alloy_consensus::BlockBody<T> impl<T, H> BlockBody for alloy_consensus::BlockBody<T, H>
where where
T: SignedTransaction, T: SignedTransaction,
H: BlockHeader,
{ {
type Transaction = T; type Transaction = T;
type OmmerHeader = Header; type OmmerHeader = H;
fn transactions(&self) -> &[Self::Transaction] { fn transactions(&self) -> &[Self::Transaction] {
&self.transactions &self.transactions

View File

@ -11,7 +11,6 @@ pub mod error;
pub mod header; pub mod header;
use alloc::{fmt, vec::Vec}; use alloc::{fmt, vec::Vec};
use alloy_consensus::Header;
use alloy_primitives::{Address, B256}; use alloy_primitives::{Address, B256};
use alloy_rlp::{Decodable, Encodable}; use alloy_rlp::{Decodable, Encodable};
@ -178,12 +177,13 @@ pub trait Block:
} }
} }
impl<T> Block for alloy_consensus::Block<T> impl<T, H> Block for alloy_consensus::Block<T, H>
where where
T: SignedTransaction, T: SignedTransaction,
H: BlockHeader,
{ {
type Header = Header; type Header = H;
type Body = alloy_consensus::BlockBody<T>; type Body = alloy_consensus::BlockBody<T, H>;
fn new(header: Self::Header, body: Self::Body) -> Self { fn new(header: Self::Header, body: Self::Body) -> Self {
Self { header, body } Self { header, body }
@ -238,9 +238,10 @@ pub trait TestBlock: Block<Header: crate::test_utils::TestHeader> {
} }
#[cfg(any(test, feature = "test-utils"))] #[cfg(any(test, feature = "test-utils"))]
impl<T> TestBlock for alloy_consensus::Block<T> impl<T, H> TestBlock for alloy_consensus::Block<T, H>
where where
T: SignedTransaction, T: SignedTransaction,
H: crate::test_utils::TestHeader,
{ {
fn body_mut(&mut self) -> &mut Self::Body { fn body_mut(&mut self) -> &mut Self::Body {
&mut self.body &mut self.body

View File

@ -1,5 +1,6 @@
//! Test utilities for the block header. //! Test utilities for the block header.
use crate::BlockHeader;
use alloy_consensus::Header; use alloy_consensus::Header;
use alloy_primitives::{BlockHash, BlockNumber, B256, U256}; use alloy_primitives::{BlockHash, BlockNumber, B256, U256};
use proptest::{arbitrary::any, prop_compose}; use proptest::{arbitrary::any, prop_compose};
@ -8,7 +9,7 @@ use proptest_arbitrary_interop::arb;
/// A helper trait for [`Header`]s that allows for mutable access to the headers values. /// A helper trait for [`Header`]s that allows for mutable access to the headers values.
/// ///
/// This allows for modifying the header for testing purposes. /// This allows for modifying the header for testing purposes.
pub trait TestHeader { pub trait TestHeader: BlockHeader {
/// Updates the parent block hash. /// Updates the parent block hash.
fn set_parent_hash(&mut self, hash: BlockHash); fn set_parent_hash(&mut self, hash: BlockHash);

View File

@ -84,13 +84,13 @@ impl InMemorySize for PooledTransaction {
} }
} }
impl<T: InMemorySize> InMemorySize for alloy_consensus::BlockBody<T> { impl<T: InMemorySize, H: InMemorySize> InMemorySize for alloy_consensus::BlockBody<T, H> {
/// Calculates a heuristic for the in-memory size of the block body /// Calculates a heuristic for the in-memory size of the block body
#[inline] #[inline]
fn size(&self) -> usize { fn size(&self) -> usize {
self.transactions.iter().map(T::size).sum::<usize>() + self.transactions.iter().map(T::size).sum::<usize>() +
self.transactions.capacity() * core::mem::size_of::<T>() + self.transactions.capacity() * core::mem::size_of::<T>() +
self.ommers.iter().map(Header::size).sum::<usize>() + self.ommers.iter().map(H::size).sum::<usize>() +
self.ommers.capacity() * core::mem::size_of::<Header>() + self.ommers.capacity() * core::mem::size_of::<Header>() +
self.withdrawals self.withdrawals
.as_ref() .as_ref()
@ -98,7 +98,7 @@ impl<T: InMemorySize> InMemorySize for alloy_consensus::BlockBody<T> {
} }
} }
impl<T: InMemorySize> InMemorySize for alloy_consensus::Block<T> { impl<T: InMemorySize, H: InMemorySize> InMemorySize for alloy_consensus::Block<T, H> {
#[inline] #[inline]
fn size(&self) -> usize { fn size(&self) -> usize {
self.header.size() + self.body.size() self.header.size() + self.body.size()

View File

@ -1,3 +1,4 @@
use alloy_consensus::Header;
use reth_ethereum_primitives::TransactionSigned; use reth_ethereum_primitives::TransactionSigned;
#[cfg(any(test, feature = "arbitrary"))] #[cfg(any(test, feature = "arbitrary"))]
pub use reth_primitives_traits::test_utils::{generate_valid_header, valid_header_strategy}; pub use reth_primitives_traits::test_utils::{generate_valid_header, valid_header_strategy};
@ -5,12 +6,12 @@ pub use reth_primitives_traits::test_utils::{generate_valid_header, valid_header
/// Ethereum full block. /// Ethereum full block.
/// ///
/// Withdrawals can be optionally included at the end of the RLP encoded message. /// Withdrawals can be optionally included at the end of the RLP encoded message.
pub type Block<T = TransactionSigned> = alloy_consensus::Block<T>; pub type Block<T = TransactionSigned, H = Header> = alloy_consensus::Block<T, H>;
/// A response to `GetBlockBodies`, containing bodies if any bodies were found. /// A response to `GetBlockBodies`, containing bodies if any bodies were found.
/// ///
/// Withdrawals can be optionally included at the end of the RLP encoded message. /// Withdrawals can be optionally included at the end of the RLP encoded message.
pub type BlockBody<T = TransactionSigned> = alloy_consensus::BlockBody<T>; pub type BlockBody<T = TransactionSigned, H = Header> = alloy_consensus::BlockBody<T, H>;
/// Ethereum sealed block type /// Ethereum sealed block type
pub type SealedBlock<B = Block> = reth_primitives_traits::block::SealedBlock<B>; pub type SealedBlock<B = Block> = reth_primitives_traits::block::SealedBlock<B>;

View File

@ -19,7 +19,7 @@ async fn test_basic_engine_calls<C>(client: &C)
where where
C: ClientT + SubscriptionClientT + Sync + EngineApiClient<EthEngineTypes>, C: ClientT + SubscriptionClientT + Sync + EngineApiClient<EthEngineTypes>,
{ {
let block = Block::default().seal_slow(); let block = Block::<_>::default().seal_slow();
EngineApiClient::new_payload_v1(client, block_to_payload_v1(block.clone())).await; EngineApiClient::new_payload_v1(client, block_to_payload_v1(block.clone())).await;
EngineApiClient::new_payload_v2( EngineApiClient::new_payload_v2(
client, client,

View File

@ -1,6 +1,7 @@
use crate::{providers::NodeTypesForProvider, DatabaseProvider}; use crate::{providers::NodeTypesForProvider, DatabaseProvider};
use reth_db::transaction::{DbTx, DbTxMut}; use reth_db::transaction::{DbTx, DbTxMut};
use reth_node_types::{FullNodePrimitives, FullSignedTx}; use reth_node_types::{FullNodePrimitives, FullSignedTx};
use reth_primitives_traits::FullBlockHeader;
use reth_storage_api::{ChainStorageReader, ChainStorageWriter, EthStorage}; use reth_storage_api::{ChainStorageReader, ChainStorageWriter, EthStorage};
/// Trait that provides access to implementations of [`ChainStorage`] /// Trait that provides access to implementations of [`ChainStorage`]
@ -18,13 +19,14 @@ pub trait ChainStorage<Primitives: FullNodePrimitives>: Send + Sync {
Types: NodeTypesForProvider<Primitives = Primitives>; Types: NodeTypesForProvider<Primitives = Primitives>;
} }
impl<N, T> ChainStorage<N> for EthStorage<T> impl<N, T, H> ChainStorage<N> for EthStorage<T, H>
where where
T: FullSignedTx, T: FullSignedTx,
H: FullBlockHeader,
N: FullNodePrimitives< N: FullNodePrimitives<
Block = reth_primitives::Block<T>, Block = reth_primitives::Block<T, H>,
BlockHeader = alloy_consensus::Header, BlockHeader = H,
BlockBody = reth_primitives::BlockBody<T>, BlockBody = reth_primitives::BlockBody<T, H>,
SignedTx = T, SignedTx = T,
>, >,
{ {

View File

@ -10,7 +10,9 @@ use reth_db::{
DbTxUnwindExt, DbTxUnwindExt,
}; };
use reth_primitives::TransactionSigned; use reth_primitives::TransactionSigned;
use reth_primitives_traits::{Block, BlockBody, FullNodePrimitives, SignedTransaction}; use reth_primitives_traits::{
Block, BlockBody, FullBlockHeader, FullNodePrimitives, SignedTransaction,
};
use reth_storage_errors::provider::ProviderResult; use reth_storage_errors::provider::ProviderResult;
/// Trait that implements how block bodies are written to the storage. /// Trait that implements how block bodies are written to the storage.
@ -81,26 +83,28 @@ impl<T, Provider, Primitives: FullNodePrimitives> ChainStorageReader<Provider, P
/// Ethereum storage implementation. /// Ethereum storage implementation.
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct EthStorage<T = TransactionSigned>(std::marker::PhantomData<T>); pub struct EthStorage<T = TransactionSigned, H = Header>(std::marker::PhantomData<(T, H)>);
impl<T> Default for EthStorage<T> { impl<T, H> Default for EthStorage<T, H> {
fn default() -> Self { fn default() -> Self {
Self(Default::default()) Self(Default::default())
} }
} }
impl<Provider, T> BlockBodyWriter<Provider, reth_primitives::BlockBody<T>> for EthStorage<T> impl<Provider, T, H> BlockBodyWriter<Provider, reth_primitives::BlockBody<T, H>>
for EthStorage<T, H>
where where
Provider: DBProvider<Tx: DbTxMut>, Provider: DBProvider<Tx: DbTxMut>,
T: SignedTransaction, T: SignedTransaction,
H: FullBlockHeader,
{ {
fn write_block_bodies( fn write_block_bodies(
&self, &self,
provider: &Provider, provider: &Provider,
bodies: Vec<(u64, Option<reth_primitives::BlockBody<T>>)>, bodies: Vec<(u64, Option<reth_primitives::BlockBody<T, H>>)>,
_write_to: StorageLocation, _write_to: StorageLocation,
) -> ProviderResult<()> { ) -> ProviderResult<()> {
let mut ommers_cursor = provider.tx_ref().cursor_write::<tables::BlockOmmers>()?; let mut ommers_cursor = provider.tx_ref().cursor_write::<tables::BlockOmmers<H>>()?;
let mut withdrawals_cursor = let mut withdrawals_cursor =
provider.tx_ref().cursor_write::<tables::BlockWithdrawals>()?; provider.tx_ref().cursor_write::<tables::BlockWithdrawals>()?;
@ -137,14 +141,14 @@ where
} }
} }
impl<Provider, T> BlockBodyReader<Provider> for EthStorage<T> impl<Provider, T, H> BlockBodyReader<Provider> for EthStorage<T, H>
where where
Provider: DBProvider Provider:
+ ChainSpecProvider<ChainSpec: EthereumHardforks> DBProvider + ChainSpecProvider<ChainSpec: EthereumHardforks> + OmmersProvider<Header = H>,
+ OmmersProvider<Header = Header>,
T: SignedTransaction, T: SignedTransaction,
H: FullBlockHeader,
{ {
type Block = reth_primitives::Block<T>; type Block = reth_primitives::Block<T, H>;
fn read_block_bodies( fn read_block_bodies(
&self, &self,
@ -161,19 +165,19 @@ where
for (header, transactions) in inputs { for (header, transactions) in inputs {
// If we are past shanghai, then all blocks should have a withdrawal list, // If we are past shanghai, then all blocks should have a withdrawal list,
// even if empty // even if empty
let withdrawals = if chain_spec.is_shanghai_active_at_timestamp(header.timestamp) { let withdrawals = if chain_spec.is_shanghai_active_at_timestamp(header.timestamp()) {
withdrawals_cursor withdrawals_cursor
.seek_exact(header.number)? .seek_exact(header.number())?
.map(|(_, w)| w.withdrawals) .map(|(_, w)| w.withdrawals)
.unwrap_or_default() .unwrap_or_default()
.into() .into()
} else { } else {
None None
}; };
let ommers = if chain_spec.final_paris_total_difficulty(header.number).is_some() { let ommers = if chain_spec.final_paris_total_difficulty(header.number()).is_some() {
Vec::new() Vec::new()
} else { } else {
provider.ommers(header.number.into())?.unwrap_or_default() provider.ommers(header.number().into())?.unwrap_or_default()
}; };
bodies.push(reth_primitives::BlockBody { transactions, ommers, withdrawals }); bodies.push(reth_primitives::BlockBody { transactions, ommers, withdrawals });