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 {
// Set a new random block to the mock storage and request it via the network
let block_hash = rng.gen();
let mut block = Block::default();
let mut block: Block = Block::default();
block.body.transactions.push(rng_transaction(&mut rng));
mock_provider.add_block(block_hash, block.clone());

View File

@ -352,7 +352,7 @@ mod tests {
const TX: [u8; 251] = hex!("7ef8f8a0a539eb753df3b13b7e386e147d45822b67cb908c9ddc5618e3dbaa22ed00850b94deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8a4440a5e2000000558000c5fc50000000000000000000000006605a89f00000000012a10d90000000000000000000000000000000000000000000000000000000af39ac3270000000000000000000000000000000000000000000000000000000d5ea528d24e582fa68786f080069bdbfe06a43f8e67bfd31b8e4d8a8837ba41da9a82a54a0000000000000000000000006887246668a3b87f54deb3b94ba47a6f63f32985");
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() },
..Default::default()
};

View File

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

View File

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

View File

@ -5,7 +5,7 @@ use crate::{
MaybeSerdeBincodeCompat, SignedTransaction,
};
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_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
T: SignedTransaction,
H: BlockHeader,
{
type Transaction = T;
type OmmerHeader = Header;
type OmmerHeader = H;
fn transactions(&self) -> &[Self::Transaction] {
&self.transactions

View File

@ -11,7 +11,6 @@ pub mod error;
pub mod header;
use alloc::{fmt, vec::Vec};
use alloy_consensus::Header;
use alloy_primitives::{Address, B256};
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
T: SignedTransaction,
H: BlockHeader,
{
type Header = Header;
type Body = alloy_consensus::BlockBody<T>;
type Header = H;
type Body = alloy_consensus::BlockBody<T, H>;
fn new(header: Self::Header, body: Self::Body) -> Self {
Self { header, body }
@ -238,9 +238,10 @@ pub trait TestBlock: Block<Header: crate::test_utils::TestHeader> {
}
#[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
T: SignedTransaction,
H: crate::test_utils::TestHeader,
{
fn body_mut(&mut self) -> &mut Self::Body {
&mut self.body

View File

@ -1,5 +1,6 @@
//! Test utilities for the block header.
use crate::BlockHeader;
use alloy_consensus::Header;
use alloy_primitives::{BlockHash, BlockNumber, B256, U256};
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.
///
/// This allows for modifying the header for testing purposes.
pub trait TestHeader {
pub trait TestHeader: BlockHeader {
/// Updates the parent block hash.
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
#[inline]
fn size(&self) -> usize {
self.transactions.iter().map(T::size).sum::<usize>() +
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.withdrawals
.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]
fn size(&self) -> usize {
self.header.size() + self.body.size()

View File

@ -1,3 +1,4 @@
use alloy_consensus::Header;
use reth_ethereum_primitives::TransactionSigned;
#[cfg(any(test, feature = "arbitrary"))]
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.
///
/// 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.
///
/// 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
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
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_v2(
client,

View File

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

View File

@ -10,7 +10,9 @@ use reth_db::{
DbTxUnwindExt,
};
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;
/// 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.
#[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 {
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
Provider: DBProvider<Tx: DbTxMut>,
T: SignedTransaction,
H: FullBlockHeader,
{
fn write_block_bodies(
&self,
provider: &Provider,
bodies: Vec<(u64, Option<reth_primitives::BlockBody<T>>)>,
bodies: Vec<(u64, Option<reth_primitives::BlockBody<T, H>>)>,
_write_to: StorageLocation,
) -> 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 =
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
Provider: DBProvider
+ ChainSpecProvider<ChainSpec: EthereumHardforks>
+ OmmersProvider<Header = Header>,
Provider:
DBProvider + ChainSpecProvider<ChainSpec: EthereumHardforks> + OmmersProvider<Header = H>,
T: SignedTransaction,
H: FullBlockHeader,
{
type Block = reth_primitives::Block<T>;
type Block = reth_primitives::Block<T, H>;
fn read_block_bodies(
&self,
@ -161,19 +165,19 @@ where
for (header, transactions) in inputs {
// If we are past shanghai, then all blocks should have a withdrawal list,
// 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
.seek_exact(header.number)?
.seek_exact(header.number())?
.map(|(_, w)| w.withdrawals)
.unwrap_or_default()
.into()
} else {
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()
} 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 });