Skip to main content

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