reth_primitives_traits/
size.rs

1use alloc::vec::Vec;
2use alloy_consensus::{
3    transaction::PooledTransaction, Header, TxEip1559, TxEip2930, TxEip4844, TxEip4844Variant,
4    TxEip4844WithSidecar, TxEip7702, TxEnvelope, TxLegacy, TxType,
5};
6use alloy_eips::eip4895::Withdrawals;
7use alloy_primitives::{PrimitiveSignature as Signature, TxHash, B256};
8use revm_primitives::Log;
9
10/// Trait for calculating a heuristic for the in-memory size of a struct.
11#[auto_impl::auto_impl(&, Arc, Box)]
12pub trait InMemorySize {
13    /// Returns a heuristic for the in-memory size of a struct.
14    fn size(&self) -> usize;
15}
16
17impl<T: InMemorySize> InMemorySize for alloy_consensus::Signed<T> {
18    fn size(&self) -> usize {
19        T::size(self.tx()) + self.signature().size() + core::mem::size_of::<B256>()
20    }
21}
22
23/// Implement `InMemorySize` for a type with `size_of`
24macro_rules! impl_in_mem_size_size_of {
25    ($($ty:ty),*) => {
26        $(
27            impl InMemorySize for $ty {
28                #[inline]
29                fn size(&self) -> usize {
30                    core::mem::size_of::<Self>()
31                }
32            }
33        )*
34    };
35}
36
37impl_in_mem_size_size_of!(Signature, TxHash, TxType);
38
39/// Implement `InMemorySize` for a type with a native `size` method.
40macro_rules! impl_in_mem_size {
41    ($($ty:ty),*) => {
42        $(
43            impl InMemorySize for $ty {
44                #[inline]
45                fn size(&self) -> usize {
46                   Self::size(self)
47                }
48            }
49        )*
50    };
51}
52
53impl_in_mem_size!(
54    Header,
55    TxLegacy,
56    TxEip2930,
57    TxEip1559,
58    TxEip7702,
59    TxEip4844,
60    TxEip4844Variant,
61    TxEip4844WithSidecar
62);
63
64#[cfg(feature = "op")]
65impl_in_mem_size_size_of!(op_alloy_consensus::OpTxType);
66
67impl InMemorySize for alloy_consensus::Receipt {
68    fn size(&self) -> usize {
69        let Self { status, cumulative_gas_used, logs } = self;
70        core::mem::size_of_val(status) +
71            core::mem::size_of_val(cumulative_gas_used) +
72            logs.capacity() * core::mem::size_of::<Log>()
73    }
74}
75
76impl InMemorySize for PooledTransaction {
77    fn size(&self) -> usize {
78        match self {
79            Self::Legacy(tx) => tx.size(),
80            Self::Eip2930(tx) => tx.size(),
81            Self::Eip1559(tx) => tx.size(),
82            Self::Eip4844(tx) => tx.size(),
83            Self::Eip7702(tx) => tx.size(),
84        }
85    }
86}
87
88impl InMemorySize for TxEnvelope {
89    fn size(&self) -> usize {
90        match self {
91            Self::Legacy(tx) => tx.size(),
92            Self::Eip2930(tx) => tx.size(),
93            Self::Eip1559(tx) => tx.size(),
94            Self::Eip4844(tx) => tx.size(),
95            Self::Eip7702(tx) => tx.size(),
96        }
97    }
98}
99
100impl<T: InMemorySize, H: InMemorySize> InMemorySize for alloy_consensus::BlockBody<T, H> {
101    /// Calculates a heuristic for the in-memory size of the block body
102    #[inline]
103    fn size(&self) -> usize {
104        self.transactions.iter().map(T::size).sum::<usize>() +
105            self.transactions.capacity() * core::mem::size_of::<T>() +
106            self.ommers.iter().map(H::size).sum::<usize>() +
107            self.ommers.capacity() * core::mem::size_of::<Header>() +
108            self.withdrawals
109                .as_ref()
110                .map_or(core::mem::size_of::<Option<Withdrawals>>(), Withdrawals::total_size)
111    }
112}
113
114impl<T: InMemorySize, H: InMemorySize> InMemorySize for alloy_consensus::Block<T, H> {
115    #[inline]
116    fn size(&self) -> usize {
117        self.header.size() + self.body.size()
118    }
119}
120
121impl<T: InMemorySize> InMemorySize for Vec<T> {
122    fn size(&self) -> usize {
123        // Note: This does not track additional capacity
124        self.iter().map(T::size).sum::<usize>()
125    }
126}
127
128/// Implementation for optimism types
129#[cfg(feature = "op")]
130mod op {
131    use super::*;
132
133    impl InMemorySize for op_alloy_consensus::OpDepositReceipt {
134        fn size(&self) -> usize {
135            let Self { inner, deposit_nonce, deposit_receipt_version } = self;
136            inner.size() +
137                core::mem::size_of_val(deposit_nonce) +
138                core::mem::size_of_val(deposit_receipt_version)
139        }
140    }
141
142    impl InMemorySize for op_alloy_consensus::OpTypedTransaction {
143        fn size(&self) -> usize {
144            match self {
145                Self::Legacy(tx) => tx.size(),
146                Self::Eip2930(tx) => tx.size(),
147                Self::Eip1559(tx) => tx.size(),
148                Self::Eip7702(tx) => tx.size(),
149                Self::Deposit(tx) => tx.size(),
150            }
151        }
152    }
153
154    impl InMemorySize for op_alloy_consensus::OpPooledTransaction {
155        fn size(&self) -> usize {
156            match self {
157                Self::Legacy(tx) => tx.size(),
158                Self::Eip2930(tx) => tx.size(),
159                Self::Eip1559(tx) => tx.size(),
160                Self::Eip7702(tx) => tx.size(),
161            }
162        }
163    }
164
165    impl InMemorySize for op_alloy_consensus::OpTxEnvelope {
166        fn size(&self) -> usize {
167            match self {
168                Self::Legacy(tx) => tx.size(),
169                Self::Eip2930(tx) => tx.size(),
170                Self::Eip1559(tx) => tx.size(),
171                Self::Eip7702(tx) => tx.size(),
172                Self::Deposit(tx) => tx.size(),
173            }
174        }
175    }
176}
177#[cfg(test)]
178mod tests {
179    use super::*;
180
181    // ensures we don't have any recursion in the `InMemorySize` impls
182    #[test]
183    fn no_in_memory_no_recursion() {
184        fn assert_no_recursion<T: InMemorySize + Default>() {
185            let _ = T::default().size();
186        }
187        assert_no_recursion::<Header>();
188        assert_no_recursion::<TxLegacy>();
189        assert_no_recursion::<TxEip2930>();
190        assert_no_recursion::<TxEip1559>();
191        assert_no_recursion::<TxEip7702>();
192        assert_no_recursion::<TxEip4844>();
193    }
194}