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