From eccff7d24b991746af8a51346cd54361b5992bca Mon Sep 17 00:00:00 2001 From: Tuan Tran Date: Mon, 11 Nov 2024 23:54:00 +0700 Subject: [PATCH] chore(reth_primitives): Use trait for `size` methods in primitive types (#12201) Co-authored-by: Matthias Seitz --- Cargo.lock | 4 +++ crates/net/downloaders/Cargo.toml | 4 ++- crates/net/downloaders/src/bodies/bodies.rs | 1 + crates/net/downloaders/src/bodies/request.rs | 1 + crates/net/p2p/Cargo.toml | 8 +++-- crates/net/p2p/src/bodies/response.rs | 21 +++++++------ crates/primitives-traits/src/header/sealed.rs | 6 +++- crates/primitives-traits/src/lib.rs | 4 +++ crates/primitives-traits/src/size.rs | 5 +++ crates/primitives/src/block.rs | 23 +++++++++----- crates/primitives/src/transaction/mod.rs | 31 ++++++++++--------- crates/prune/prune/Cargo.toml | 1 + .../src/segments/user/receipts_by_logs.rs | 2 +- crates/transaction-pool/Cargo.toml | 10 ++++-- .../transaction-pool/src/test_utils/mock.rs | 2 +- crates/transaction-pool/src/validate/eth.rs | 3 +- 16 files changed, 84 insertions(+), 42 deletions(-) create mode 100644 crates/primitives-traits/src/size.rs diff --git a/Cargo.lock b/Cargo.lock index 0c64ed9a9..0990a4699 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7039,6 +7039,7 @@ dependencies = [ "reth-network-p2p", "reth-network-peers", "reth-primitives", + "reth-primitives-traits", "reth-provider", "reth-storage-api", "reth-tasks", @@ -7828,6 +7829,7 @@ dependencies = [ "reth-network-peers", "reth-network-types", "reth-primitives", + "reth-primitives-traits", "reth-storage-errors", "tokio", "tracing", @@ -8570,6 +8572,7 @@ dependencies = [ "reth-errors", "reth-exex-types", "reth-metrics", + "reth-primitives-traits", "reth-provider", "reth-prune-types", "reth-stages", @@ -9192,6 +9195,7 @@ dependencies = [ "reth-fs-util", "reth-metrics", "reth-primitives", + "reth-primitives-traits", "reth-provider", "reth-storage-api", "reth-tasks", diff --git a/crates/net/downloaders/Cargo.toml b/crates/net/downloaders/Cargo.toml index 272db6fc6..69a59f698 100644 --- a/crates/net/downloaders/Cargo.toml +++ b/crates/net/downloaders/Cargo.toml @@ -18,6 +18,7 @@ reth-consensus.workspace = true reth-network-p2p.workspace = true reth-network-peers.workspace = true reth-primitives.workspace = true +reth-primitives-traits.workspace = true reth-storage-api.workspace = true reth-tasks.workspace = true @@ -80,5 +81,6 @@ test-utils = [ "reth-chainspec/test-utils", "reth-primitives/test-utils", "reth-db-api?/test-utils", - "reth-provider/test-utils" + "reth-provider/test-utils", + "reth-primitives-traits/test-utils" ] diff --git a/crates/net/downloaders/src/bodies/bodies.rs b/crates/net/downloaders/src/bodies/bodies.rs index 314f3a090..af113fdb3 100644 --- a/crates/net/downloaders/src/bodies/bodies.rs +++ b/crates/net/downloaders/src/bodies/bodies.rs @@ -14,6 +14,7 @@ use reth_network_p2p::{ error::{DownloadError, DownloadResult}, }; use reth_primitives::SealedHeader; +use reth_primitives_traits::size::InMemorySize; use reth_storage_api::HeaderProvider; use reth_tasks::{TaskSpawner, TokioTaskExecutor}; use std::{ diff --git a/crates/net/downloaders/src/bodies/request.rs b/crates/net/downloaders/src/bodies/request.rs index c2b36732b..5ab44ed08 100644 --- a/crates/net/downloaders/src/bodies/request.rs +++ b/crates/net/downloaders/src/bodies/request.rs @@ -9,6 +9,7 @@ use reth_network_p2p::{ }; use reth_network_peers::{PeerId, WithPeerId}; use reth_primitives::{BlockBody, GotExpected, SealedBlock, SealedHeader}; +use reth_primitives_traits::InMemorySize; use std::{ collections::VecDeque, mem, diff --git a/crates/net/p2p/Cargo.toml b/crates/net/p2p/Cargo.toml index 3b6d74c9d..898553969 100644 --- a/crates/net/p2p/Cargo.toml +++ b/crates/net/p2p/Cargo.toml @@ -14,6 +14,7 @@ workspace = true [dependencies] # reth reth-primitives.workspace = true +reth-primitives-traits.workspace = true reth-eth-wire-types.workspace = true reth-consensus.workspace = true reth-network-peers.workspace = true @@ -32,7 +33,6 @@ tokio = { workspace = true, features = ["sync"] } auto_impl.workspace = true tracing.workspace = true derive_more.workspace = true - parking_lot = { workspace = true, optional = true } [dev-dependencies] @@ -47,11 +47,13 @@ test-utils = [ "reth-consensus/test-utils", "parking_lot", "reth-network-types/test-utils", - "reth-primitives/test-utils" + "reth-primitives/test-utils", + "reth-primitives-traits/test-utils" ] std = [ "reth-consensus/std", "reth-primitives/std", "alloy-eips/std", - "alloy-primitives/std" + "alloy-primitives/std", + "reth-primitives-traits/std" ] diff --git a/crates/net/p2p/src/bodies/response.rs b/crates/net/p2p/src/bodies/response.rs index 8ae840fbf..0a45008ac 100644 --- a/crates/net/p2p/src/bodies/response.rs +++ b/crates/net/p2p/src/bodies/response.rs @@ -1,5 +1,6 @@ use alloy_primitives::{BlockNumber, U256}; use reth_primitives::{SealedBlock, SealedHeader}; +use reth_primitives_traits::InMemorySize; /// The block response #[derive(PartialEq, Eq, Debug, Clone)] @@ -19,15 +20,6 @@ impl BlockResponse { } } - /// Calculates a heuristic for the in-memory size of the [`BlockResponse`]. - #[inline] - pub fn size(&self) -> usize { - match self { - Self::Full(block) => SealedBlock::size(block), - Self::Empty(header) => SealedHeader::size(header), - } - } - /// Return the block number pub fn block_number(&self) -> BlockNumber { self.header().number @@ -41,3 +33,14 @@ impl BlockResponse { } } } + +impl InMemorySize for BlockResponse { + /// Calculates a heuristic for the in-memory size of the [`BlockResponse`]. + #[inline] + fn size(&self) -> usize { + match self { + Self::Full(block) => SealedBlock::size(block), + Self::Empty(header) => SealedHeader::size(header), + } + } +} diff --git a/crates/primitives-traits/src/header/sealed.rs b/crates/primitives-traits/src/header/sealed.rs index 799f698f1..995c13748 100644 --- a/crates/primitives-traits/src/header/sealed.rs +++ b/crates/primitives-traits/src/header/sealed.rs @@ -1,3 +1,5 @@ +use crate::InMemorySize; + use super::Header; use alloy_consensus::Sealed; use alloy_eips::BlockNumHash; @@ -59,10 +61,12 @@ impl SealedHeader { pub fn num_hash(&self) -> BlockNumHash { BlockNumHash::new(self.number, self.hash) } +} +impl InMemorySize for SealedHeader { /// Calculates a heuristic for the in-memory size of the [`SealedHeader`]. #[inline] - pub fn size(&self) -> usize { + fn size(&self) -> usize { self.header.size() + mem::size_of::() } } diff --git a/crates/primitives-traits/src/lib.rs b/crates/primitives-traits/src/lib.rs index 3d8aea04e..6fcb725cf 100644 --- a/crates/primitives-traits/src/lib.rs +++ b/crates/primitives-traits/src/lib.rs @@ -73,3 +73,7 @@ pub use header::{Header, HeaderError, SealedHeader}; pub mod serde_bincode_compat { pub use super::header::{serde_bincode_compat as header, serde_bincode_compat::*}; } + +/// Heuristic size trait +pub mod size; +pub use size::InMemorySize; diff --git a/crates/primitives-traits/src/size.rs b/crates/primitives-traits/src/size.rs new file mode 100644 index 000000000..173f8cedc --- /dev/null +++ b/crates/primitives-traits/src/size.rs @@ -0,0 +1,5 @@ +/// Trait for calculating a heuristic for the in-memory size of a struct. +pub trait InMemorySize { + /// Returns a heuristic for the in-memory size of a struct. + fn size(&self) -> usize; +} diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs index b54a7bd0f..275f86c5b 100644 --- a/crates/primitives/src/block.rs +++ b/crates/primitives/src/block.rs @@ -6,6 +6,7 @@ use alloy_rlp::{Decodable, Encodable, RlpDecodable, RlpEncodable}; use derive_more::{Deref, DerefMut}; #[cfg(any(test, feature = "arbitrary"))] pub use reth_primitives_traits::test_utils::{generate_valid_header, valid_header_strategy}; +use reth_primitives_traits::InMemorySize; use serde::{Deserialize, Serialize}; /// Ethereum full block. @@ -84,10 +85,12 @@ impl Block { let senders = self.senders()?; Some(BlockWithSenders { block: self, senders }) } +} +impl InMemorySize for Block { /// Calculates a heuristic for the in-memory size of the [`Block`]. #[inline] - pub fn size(&self) -> usize { + fn size(&self) -> usize { self.header.size() + self.body.size() } } @@ -376,12 +379,6 @@ impl SealedBlock { Block { header: self.header.unseal(), body: self.body } } - /// Calculates a heuristic for the in-memory size of the [`SealedBlock`]. - #[inline] - pub fn size(&self) -> usize { - self.header.size() + self.body.size() - } - /// Calculates the total gas used by blob transactions in the sealed block. pub fn blob_gas_used(&self) -> u64 { self.blob_transactions().iter().filter_map(|tx| tx.blob_gas_used()).sum() @@ -431,6 +428,14 @@ impl SealedBlock { } } +impl InMemorySize for SealedBlock { + /// Calculates a heuristic for the in-memory size of the [`SealedBlock`]. + #[inline] + fn size(&self) -> usize { + self.header.size() + self.body.size() + } +} + impl From for Block { fn from(block: SealedBlock) -> Self { block.unseal() @@ -625,10 +630,12 @@ impl BlockBody { pub fn transactions(&self) -> impl Iterator + '_ { self.transactions.iter() } +} +impl InMemorySize for BlockBody { /// Calculates a heuristic for the in-memory size of the [`BlockBody`]. #[inline] - pub fn size(&self) -> usize { + fn size(&self) -> usize { self.transactions.iter().map(TransactionSigned::size).sum::() + self.transactions.capacity() * core::mem::size_of::() + self.ommers.iter().map(Header::size).sum::() + diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs index 685fd29a3..485de92ea 100644 --- a/crates/primitives/src/transaction/mod.rs +++ b/crates/primitives/src/transaction/mod.rs @@ -24,6 +24,7 @@ use once_cell::sync::Lazy as LazyLock; #[cfg(feature = "optimism")] use op_alloy_consensus::DepositTransaction; use rayon::prelude::{IntoParallelIterator, ParallelIterator}; +use reth_primitives_traits::InMemorySize; use serde::{Deserialize, Serialize}; use signature::decode_with_eip155_chain_id; #[cfg(feature = "std")] @@ -472,20 +473,6 @@ impl Transaction { } } - /// Calculates a heuristic for the in-memory size of the [Transaction]. - #[inline] - pub fn size(&self) -> usize { - match self { - Self::Legacy(tx) => tx.size(), - Self::Eip2930(tx) => tx.size(), - Self::Eip1559(tx) => tx.size(), - Self::Eip4844(tx) => tx.size(), - Self::Eip7702(tx) => tx.size(), - #[cfg(feature = "optimism")] - Self::Deposit(tx) => tx.size(), - } - } - /// Returns true if the transaction is a legacy transaction. #[inline] pub const fn is_legacy(&self) -> bool { @@ -557,6 +544,22 @@ impl Transaction { } } +impl InMemorySize for Transaction { + /// Calculates a heuristic for the in-memory size of the [Transaction]. + #[inline] + fn size(&self) -> usize { + match self { + Self::Legacy(tx) => tx.size(), + Self::Eip2930(tx) => tx.size(), + Self::Eip1559(tx) => tx.size(), + Self::Eip4844(tx) => tx.size(), + Self::Eip7702(tx) => tx.size(), + #[cfg(feature = "optimism")] + Self::Deposit(tx) => tx.size(), + } + } +} + #[cfg(any(test, feature = "reth-codec"))] impl reth_codecs::Compact for Transaction { // Serializes the TxType to the buffer if necessary, returning 2 bits of the type as an diff --git a/crates/prune/prune/Cargo.toml b/crates/prune/prune/Cargo.toml index 2f2a37d5b..4df9ace81 100644 --- a/crates/prune/prune/Cargo.toml +++ b/crates/prune/prune/Cargo.toml @@ -41,6 +41,7 @@ rustc-hash.workspace = true # reth reth-db = { workspace = true, features = ["test-utils"] } reth-stages = { workspace = true, features = ["test-utils"] } +reth-primitives-traits = { workspace = true, features = ["arbitrary"] } reth-testing-utils.workspace = true reth-tracing.workspace = true diff --git a/crates/prune/prune/src/segments/user/receipts_by_logs.rs b/crates/prune/prune/src/segments/user/receipts_by_logs.rs index ee2accee1..ee404b074 100644 --- a/crates/prune/prune/src/segments/user/receipts_by_logs.rs +++ b/crates/prune/prune/src/segments/user/receipts_by_logs.rs @@ -10,7 +10,6 @@ use reth_prune_types::{ SegmentOutput, MINIMUM_PRUNING_DISTANCE, }; use tracing::{instrument, trace}; - #[derive(Debug)] pub struct ReceiptsByLogs { config: ReceiptsLogPruneConfig, @@ -223,6 +222,7 @@ mod tests { use assert_matches::assert_matches; use reth_db::tables; use reth_db_api::{cursor::DbCursorRO, transaction::DbTx}; + use reth_primitives_traits::InMemorySize; use reth_provider::{DatabaseProviderFactory, PruneCheckpointReader, TransactionsProvider}; use reth_prune_types::{PruneLimiter, PruneMode, PruneSegment, ReceiptsLogPruneConfig}; use reth_stages::test_utils::{StorageKind, TestStageDB}; diff --git a/crates/transaction-pool/Cargo.toml b/crates/transaction-pool/Cargo.toml index 1bfb10d86..7c760c81c 100644 --- a/crates/transaction-pool/Cargo.toml +++ b/crates/transaction-pool/Cargo.toml @@ -17,6 +17,7 @@ reth-chain-state.workspace = true reth-chainspec.workspace = true reth-eth-wire-types.workspace = true reth-primitives = { workspace = true, features = ["c-kzg", "secp256k1"] } +reth-primitives-traits.workspace = true reth-execution-types.workspace = true reth-fs-util.workspace = true reth-storage-api.workspace = true @@ -50,6 +51,7 @@ bitflags.workspace = true auto_impl.workspace = true smallvec.workspace = true + # testing rand = { workspace = true, optional = true } paste = { workspace = true, optional = true } @@ -84,7 +86,7 @@ serde = [ "parking_lot/serde", "rand?/serde", "revm/serde", - "smallvec/serde" + "smallvec/serde", ] test-utils = [ "rand", @@ -94,7 +96,8 @@ test-utils = [ "reth-chainspec/test-utils", "reth-primitives/test-utils", "reth-provider/test-utils", - "revm/test-utils" + "revm/test-utils", + "reth-primitives-traits/test-utils", ] arbitrary = [ "proptest", @@ -107,7 +110,8 @@ arbitrary = [ "alloy-primitives/arbitrary", "bitflags/arbitrary", "revm/arbitrary", - "smallvec/arbitrary" + "reth-primitives-traits/arbitrary", + "smallvec/arbitrary", ] [[bench]] diff --git a/crates/transaction-pool/src/test_utils/mock.rs b/crates/transaction-pool/src/test_utils/mock.rs index 92f746652..fc43349f3 100644 --- a/crates/transaction-pool/src/test_utils/mock.rs +++ b/crates/transaction-pool/src/test_utils/mock.rs @@ -28,7 +28,6 @@ use reth_primitives::{ transaction::TryFromRecoveredTransactionError, PooledTransactionsElementEcRecovered, Transaction, TransactionSigned, TransactionSignedEcRecovered, TxType, }; - use std::{ops::Range, sync::Arc, time::Instant, vec::IntoIter}; /// A transaction pool implementation using [`MockOrdering`] for transaction ordering. @@ -1007,6 +1006,7 @@ impl proptest::arbitrary::Arbitrary for MockTransaction { fn arbitrary_with(_: Self::Parameters) -> Self::Strategy { use proptest::prelude::Strategy; use proptest_arbitrary_interop::arb; + use reth_primitives_traits::size::InMemorySize; arb::<(Transaction, Address, B256)>() .prop_map(|(tx, sender, tx_hash)| match &tx { diff --git a/crates/transaction-pool/src/validate/eth.rs b/crates/transaction-pool/src/validate/eth.rs index 62e9f3f29..d5f7101eb 100644 --- a/crates/transaction-pool/src/validate/eth.rs +++ b/crates/transaction-pool/src/validate/eth.rs @@ -17,7 +17,8 @@ use alloy_consensus::constants::{ }; use alloy_eips::eip4844::MAX_BLOBS_PER_BLOCK; use reth_chainspec::{ChainSpec, EthereumHardforks}; -use reth_primitives::{GotExpected, InvalidTransactionError, SealedBlock}; +use reth_primitives::{InvalidTransactionError, SealedBlock}; +use reth_primitives_traits::GotExpected; use reth_storage_api::{AccountReader, StateProviderFactory}; use reth_tasks::TaskSpawner; use revm::{