reth_db_api/models/
mod.rs

1//! Implements data structures specific to the database
2
3use crate::{
4    table::{Compress, Decode, Decompress, Encode},
5    DatabaseError,
6};
7use alloy_consensus::Header;
8use alloy_genesis::GenesisAccount;
9use alloy_primitives::{Address, Bytes, Log, B256, U256};
10use reth_codecs::{add_arbitrary_tests, Compact};
11use reth_ethereum_primitives::{Receipt, TransactionSigned, TxType};
12use reth_primitives_traits::{Account, Bytecode, StorageEntry};
13use reth_prune_types::{PruneCheckpoint, PruneSegment};
14use reth_stages_types::StageCheckpoint;
15use reth_trie_common::{StoredNibbles, StoredNibblesSubKey, *};
16use serde::{Deserialize, Serialize};
17
18pub mod accounts;
19pub mod blocks;
20pub mod integer_list;
21pub mod sharded_key;
22pub mod storage_sharded_key;
23
24pub use accounts::*;
25pub use blocks::*;
26pub use integer_list::IntegerList;
27pub use reth_db_models::{
28    AccountBeforeTx, ClientVersion, StaticFileBlockWithdrawals, StoredBlockBodyIndices,
29    StoredBlockWithdrawals,
30};
31pub use sharded_key::ShardedKey;
32
33/// Macro that implements [`Encode`] and [`Decode`] for uint types.
34macro_rules! impl_uints {
35    ($($name:tt),+) => {
36        $(
37            impl Encode for $name {
38                type Encoded = [u8; std::mem::size_of::<$name>()];
39
40                fn encode(self) -> Self::Encoded {
41                    self.to_be_bytes()
42                }
43            }
44
45            impl Decode for $name {
46                fn decode(value: &[u8]) -> Result<Self, $crate::DatabaseError> {
47                    Ok(
48                        $name::from_be_bytes(
49                            value.try_into().map_err(|_| $crate::DatabaseError::Decode)?
50                        )
51                    )
52                }
53            }
54        )+
55    };
56}
57
58impl_uints!(u64, u32, u16, u8);
59
60impl Encode for Vec<u8> {
61    type Encoded = Self;
62
63    fn encode(self) -> Self::Encoded {
64        self
65    }
66}
67
68impl Decode for Vec<u8> {
69    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
70        Ok(value.to_vec())
71    }
72
73    fn decode_owned(value: Vec<u8>) -> Result<Self, DatabaseError> {
74        Ok(value)
75    }
76}
77
78impl Encode for Address {
79    type Encoded = [u8; 20];
80
81    fn encode(self) -> Self::Encoded {
82        self.0 .0
83    }
84}
85
86impl Decode for Address {
87    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
88        Ok(Self::from_slice(value))
89    }
90}
91
92impl Encode for B256 {
93    type Encoded = [u8; 32];
94
95    fn encode(self) -> Self::Encoded {
96        self.0
97    }
98}
99
100impl Decode for B256 {
101    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
102        Ok(Self::new(value.try_into().map_err(|_| DatabaseError::Decode)?))
103    }
104}
105
106impl Encode for String {
107    type Encoded = Vec<u8>;
108
109    fn encode(self) -> Self::Encoded {
110        self.into_bytes()
111    }
112}
113
114impl Decode for String {
115    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
116        Self::decode_owned(value.to_vec())
117    }
118
119    fn decode_owned(value: Vec<u8>) -> Result<Self, DatabaseError> {
120        Self::from_utf8(value).map_err(|_| DatabaseError::Decode)
121    }
122}
123
124impl Encode for StoredNibbles {
125    type Encoded = Vec<u8>;
126
127    // Delegate to the Compact implementation
128    fn encode(self) -> Self::Encoded {
129        // NOTE: This used to be `to_compact`, but all it does is append the bytes to the buffer,
130        // so we can just use the implementation of `Into<Vec<u8>>` to reuse the buffer.
131        self.0.into()
132    }
133}
134
135impl Decode for StoredNibbles {
136    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
137        Ok(Self::from_compact(value, value.len()).0)
138    }
139}
140
141impl Encode for StoredNibblesSubKey {
142    type Encoded = Vec<u8>;
143
144    // Delegate to the Compact implementation
145    fn encode(self) -> Self::Encoded {
146        let mut buf = Vec::with_capacity(65);
147        self.to_compact(&mut buf);
148        buf
149    }
150}
151
152impl Decode for StoredNibblesSubKey {
153    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
154        Ok(Self::from_compact(value, value.len()).0)
155    }
156}
157
158impl Encode for PruneSegment {
159    type Encoded = [u8; 1];
160
161    fn encode(self) -> Self::Encoded {
162        let mut buf = [0u8];
163        self.to_compact(&mut buf.as_mut());
164        buf
165    }
166}
167
168impl Decode for PruneSegment {
169    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
170        Ok(Self::from_compact(value, value.len()).0)
171    }
172}
173
174impl Encode for ClientVersion {
175    type Encoded = Vec<u8>;
176
177    // Delegate to the Compact implementation
178    fn encode(self) -> Self::Encoded {
179        let mut buf = vec![];
180        self.to_compact(&mut buf);
181        buf
182    }
183}
184
185impl Decode for ClientVersion {
186    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
187        Ok(Self::from_compact(value, value.len()).0)
188    }
189}
190
191/// Implements compression for Compact type.
192macro_rules! impl_compression_for_compact {
193    ($($name:ident$(<$($generic:ident),*>)?),+) => {
194        $(
195            impl$(<$($generic: core::fmt::Debug + Send + Sync + Compact),*>)? Compress for $name$(<$($generic),*>)? {
196                type Compressed = Vec<u8>;
197
198                fn compress_to_buf<B: bytes::BufMut + AsMut<[u8]>>(&self, buf: &mut B) {
199                    let _ = Compact::to_compact(self, buf);
200                }
201            }
202
203            impl$(<$($generic: core::fmt::Debug + Send + Sync + Compact),*>)? Decompress for $name$(<$($generic),*>)? {
204                fn decompress(value: &[u8]) -> Result<$name$(<$($generic),*>)?, $crate::DatabaseError> {
205                    let (obj, _) = Compact::from_compact(value, value.len());
206                    Ok(obj)
207                }
208            }
209        )+
210    };
211}
212
213impl_compression_for_compact!(
214    Bytes,
215    Header,
216    Account,
217    Log,
218    Receipt,
219    TxType,
220    StorageEntry,
221    BranchNodeCompact,
222    StoredNibbles,
223    StoredNibblesSubKey,
224    StorageTrieEntry,
225    StoredBlockBodyIndices,
226    StoredBlockOmmers<H>,
227    StoredBlockWithdrawals,
228    StaticFileBlockWithdrawals,
229    Bytecode,
230    AccountBeforeTx,
231    TransactionSigned,
232    CompactU256,
233    StageCheckpoint,
234    PruneCheckpoint,
235    ClientVersion,
236    // Non-DB
237    GenesisAccount
238);
239
240#[cfg(feature = "op")]
241mod op {
242    use super::*;
243    use reth_optimism_primitives::{OpReceipt, OpTransactionSigned};
244
245    impl_compression_for_compact!(OpTransactionSigned, OpReceipt);
246}
247
248mod seismic {
249    use super::*;
250    use reth_seismic_primitives::{SeismicReceipt, SeismicTransactionSigned};
251
252    impl_compression_for_compact!(SeismicTransactionSigned, SeismicReceipt);
253}
254
255macro_rules! impl_compression_fixed_compact {
256    ($($name:tt),+) => {
257        $(
258            impl Compress for $name {
259                type Compressed = Vec<u8>;
260
261                fn uncompressable_ref(&self) -> Option<&[u8]> {
262                    Some(self.as_ref())
263                }
264
265                fn compress_to_buf<B: bytes::BufMut + AsMut<[u8]>>(&self, buf: &mut B) {
266                    let _  = Compact::to_compact(self, buf);
267                }
268            }
269
270            impl Decompress for $name {
271                fn decompress(value: &[u8]) -> Result<$name, $crate::DatabaseError> {
272                    let (obj, _) = Compact::from_compact(&value, value.len());
273                    Ok(obj)
274                }
275            }
276
277        )+
278    };
279}
280
281impl_compression_fixed_compact!(B256, Address);
282
283/// Adds wrapper structs for some primitive types so they can use `StructFlags` from Compact, when
284/// used as pure table values.
285macro_rules! add_wrapper_struct {
286    ($(($name:tt, $wrapper:tt)),+) => {
287        $(
288            /// Wrapper struct so it can use StructFlags from Compact, when used as pure table values.
289            #[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, Compact)]
290            #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
291            #[add_arbitrary_tests(compact)]
292            pub struct $wrapper(pub $name);
293
294            impl From<$name> for $wrapper {
295                fn from(value: $name) -> Self {
296                    $wrapper(value)
297                }
298            }
299
300            impl From<$wrapper> for $name {
301                fn from(value: $wrapper) -> Self {
302                    value.0
303                }
304            }
305
306            impl std::ops::Deref for $wrapper {
307                type Target = $name;
308
309                fn deref(&self) -> &Self::Target {
310                    &self.0
311                }
312            }
313
314        )+
315    };
316}
317
318add_wrapper_struct!((U256, CompactU256));
319add_wrapper_struct!((u64, CompactU64));
320add_wrapper_struct!((ClientVersion, CompactClientVersion));
321
322#[cfg(test)]
323mod tests {
324    // each value in the database has an extra field named flags that encodes metadata about other
325    // fields in the value, e.g. offset and length.
326    //
327    // this check is to ensure we do not inadvertently add too many fields to a struct which would
328    // expand the flags field and break backwards compatibility
329    #[test]
330    fn test_ensure_backwards_compatibility() {
331        use super::*;
332        use reth_codecs::{test_utils::UnusedBits, validate_bitflag_backwards_compat};
333        use reth_primitives_traits::Account;
334        use reth_prune_types::{PruneCheckpoint, PruneMode, PruneSegment};
335        use reth_stages_types::{
336            AccountHashingCheckpoint, CheckpointBlockRange, EntitiesCheckpoint,
337            ExecutionCheckpoint, HeadersCheckpoint, IndexHistoryCheckpoint, StageCheckpoint,
338            StageUnitCheckpoint, StorageHashingCheckpoint,
339        };
340        assert_eq!(Account::bitflag_encoded_bytes(), 2);
341        assert_eq!(AccountHashingCheckpoint::bitflag_encoded_bytes(), 1);
342        assert_eq!(CheckpointBlockRange::bitflag_encoded_bytes(), 1);
343        assert_eq!(CompactClientVersion::bitflag_encoded_bytes(), 0);
344        assert_eq!(CompactU256::bitflag_encoded_bytes(), 1);
345        assert_eq!(CompactU64::bitflag_encoded_bytes(), 1);
346        assert_eq!(EntitiesCheckpoint::bitflag_encoded_bytes(), 1);
347        assert_eq!(ExecutionCheckpoint::bitflag_encoded_bytes(), 0);
348        assert_eq!(HeadersCheckpoint::bitflag_encoded_bytes(), 0);
349        assert_eq!(IndexHistoryCheckpoint::bitflag_encoded_bytes(), 0);
350        assert_eq!(PruneCheckpoint::bitflag_encoded_bytes(), 1);
351        assert_eq!(PruneMode::bitflag_encoded_bytes(), 1);
352        assert_eq!(PruneSegment::bitflag_encoded_bytes(), 1);
353        assert_eq!(Receipt::bitflag_encoded_bytes(), 1);
354        assert_eq!(StageCheckpoint::bitflag_encoded_bytes(), 1);
355        assert_eq!(StageUnitCheckpoint::bitflag_encoded_bytes(), 1);
356        assert_eq!(StoredBlockBodyIndices::bitflag_encoded_bytes(), 1);
357        assert_eq!(StoredBlockWithdrawals::bitflag_encoded_bytes(), 0);
358        assert_eq!(StorageHashingCheckpoint::bitflag_encoded_bytes(), 1);
359
360        validate_bitflag_backwards_compat!(Account, UnusedBits::NotZero);
361        validate_bitflag_backwards_compat!(AccountHashingCheckpoint, UnusedBits::NotZero);
362        validate_bitflag_backwards_compat!(CheckpointBlockRange, UnusedBits::Zero);
363        validate_bitflag_backwards_compat!(CompactClientVersion, UnusedBits::Zero);
364        validate_bitflag_backwards_compat!(CompactU256, UnusedBits::NotZero);
365        validate_bitflag_backwards_compat!(CompactU64, UnusedBits::NotZero);
366        validate_bitflag_backwards_compat!(EntitiesCheckpoint, UnusedBits::Zero);
367        validate_bitflag_backwards_compat!(ExecutionCheckpoint, UnusedBits::Zero);
368        validate_bitflag_backwards_compat!(HeadersCheckpoint, UnusedBits::Zero);
369        validate_bitflag_backwards_compat!(IndexHistoryCheckpoint, UnusedBits::Zero);
370        validate_bitflag_backwards_compat!(PruneCheckpoint, UnusedBits::NotZero);
371        validate_bitflag_backwards_compat!(PruneMode, UnusedBits::Zero);
372        validate_bitflag_backwards_compat!(PruneSegment, UnusedBits::Zero);
373        validate_bitflag_backwards_compat!(Receipt, UnusedBits::Zero);
374        validate_bitflag_backwards_compat!(StageCheckpoint, UnusedBits::NotZero);
375        validate_bitflag_backwards_compat!(StageUnitCheckpoint, UnusedBits::Zero);
376        validate_bitflag_backwards_compat!(StoredBlockBodyIndices, UnusedBits::Zero);
377        validate_bitflag_backwards_compat!(StoredBlockWithdrawals, UnusedBits::Zero);
378        validate_bitflag_backwards_compat!(StorageHashingCheckpoint, UnusedBits::NotZero);
379    }
380}