reth_primitives_traits/
size.rs

1use alloc::vec::Vec;
2use alloy_consensus::{
3    transaction::TxEip4844Sidecar, EthereumTxEnvelope, Header, TxEip1559, TxEip2930, TxEip4844,
4    TxEip4844Variant, TxEip4844WithSidecar, TxEip7702, TxLegacy, TxType,
5};
6use alloy_eips::eip4895::Withdrawals;
7use alloy_primitives::{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!(Header, TxLegacy, TxEip2930, TxEip1559, TxEip7702, TxEip4844);
54
55impl<T: TxEip4844Sidecar> InMemorySize for TxEip4844Variant<T> {
56    #[inline]
57    fn size(&self) -> usize {
58        Self::size(self)
59    }
60}
61
62impl<T: TxEip4844Sidecar> InMemorySize for TxEip4844WithSidecar<T> {
63    #[inline]
64    fn size(&self) -> usize {
65        Self::size(self)
66    }
67}
68
69#[cfg(feature = "op")]
70impl_in_mem_size_size_of!(op_alloy_consensus::OpTxType);
71
72impl InMemorySize for alloy_consensus::Receipt {
73    fn size(&self) -> usize {
74        let Self { status, cumulative_gas_used, logs } = self;
75        core::mem::size_of_val(status) +
76            core::mem::size_of_val(cumulative_gas_used) +
77            logs.capacity() * core::mem::size_of::<Log>()
78    }
79}
80
81impl<T: InMemorySize> InMemorySize for EthereumTxEnvelope<T> {
82    fn size(&self) -> usize {
83        match self {
84            Self::Legacy(tx) => tx.size(),
85            Self::Eip2930(tx) => tx.size(),
86            Self::Eip1559(tx) => tx.size(),
87            Self::Eip4844(tx) => tx.size(),
88            Self::Eip7702(tx) => tx.size(),
89        }
90    }
91}
92
93impl<T: InMemorySize, H: InMemorySize> InMemorySize for alloy_consensus::BlockBody<T, H> {
94    /// Calculates a heuristic for the in-memory size of the block body
95    #[inline]
96    fn size(&self) -> usize {
97        self.transactions.iter().map(T::size).sum::<usize>() +
98            self.transactions.capacity() * core::mem::size_of::<T>() +
99            self.ommers.iter().map(H::size).sum::<usize>() +
100            self.ommers.capacity() * core::mem::size_of::<Header>() +
101            self.withdrawals
102                .as_ref()
103                .map_or(core::mem::size_of::<Option<Withdrawals>>(), Withdrawals::total_size)
104    }
105}
106
107impl<T: InMemorySize, H: InMemorySize> InMemorySize for alloy_consensus::Block<T, H> {
108    #[inline]
109    fn size(&self) -> usize {
110        self.header.size() + self.body.size()
111    }
112}
113
114impl<T: InMemorySize> InMemorySize for Vec<T> {
115    fn size(&self) -> usize {
116        // Note: This does not track additional capacity
117        self.iter().map(T::size).sum::<usize>()
118    }
119}
120
121impl InMemorySize for u64 {
122    fn size(&self) -> usize {
123        core::mem::size_of::<Self>()
124    }
125}
126
127/// Implementation for optimism types
128#[cfg(feature = "op")]
129mod op {
130    use super::*;
131
132    impl InMemorySize for op_alloy_consensus::OpDepositReceipt {
133        fn size(&self) -> usize {
134            let Self { inner, deposit_nonce, deposit_receipt_version } = self;
135            inner.size() +
136                core::mem::size_of_val(deposit_nonce) +
137                core::mem::size_of_val(deposit_receipt_version)
138        }
139    }
140
141    impl InMemorySize for op_alloy_consensus::OpTypedTransaction {
142        fn size(&self) -> usize {
143            match self {
144                Self::Legacy(tx) => tx.size(),
145                Self::Eip2930(tx) => tx.size(),
146                Self::Eip1559(tx) => tx.size(),
147                Self::Eip7702(tx) => tx.size(),
148                Self::Deposit(tx) => tx.size(),
149            }
150        }
151    }
152
153    impl InMemorySize for op_alloy_consensus::OpPooledTransaction {
154        fn size(&self) -> usize {
155            match self {
156                Self::Legacy(tx) => tx.size(),
157                Self::Eip2930(tx) => tx.size(),
158                Self::Eip1559(tx) => tx.size(),
159                Self::Eip7702(tx) => tx.size(),
160            }
161        }
162    }
163
164    impl InMemorySize for op_alloy_consensus::OpTxEnvelope {
165        fn size(&self) -> usize {
166            match self {
167                Self::Legacy(tx) => tx.size(),
168                Self::Eip2930(tx) => tx.size(),
169                Self::Eip1559(tx) => tx.size(),
170                Self::Eip7702(tx) => tx.size(),
171                Self::Deposit(tx) => tx.size(),
172            }
173        }
174    }
175}
176#[cfg(test)]
177mod tests {
178    use super::*;
179
180    // ensures we don't have any recursion in the `InMemorySize` impls
181    #[test]
182    fn no_in_memory_no_recursion() {
183        fn assert_no_recursion<T: InMemorySize + Default>() {
184            let _ = T::default().size();
185        }
186        assert_no_recursion::<Header>();
187        assert_no_recursion::<TxLegacy>();
188        assert_no_recursion::<TxEip2930>();
189        assert_no_recursion::<TxEip1559>();
190        assert_no_recursion::<TxEip7702>();
191        assert_no_recursion::<TxEip4844>();
192    }
193}