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