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