Skip to main content

reth_db_api/models/
mod.rs

1//! Implements data structures specific to the database
2
3use crate::{
4    table::{Decode, Encode},
5    DatabaseError,
6};
7use alloy_primitives::{Address, B256, U256};
8use reth_codecs::{add_arbitrary_tests, impl_compression_for_compact, Compact};
9use reth_prune_types::PruneSegment;
10use reth_trie_common::{StoredNibbles, StoredNibblesSubKey, *};
11use serde::{Deserialize, Serialize};
12
13pub mod accounts;
14pub mod bal;
15pub mod blocks;
16pub mod integer_list;
17pub mod metadata;
18pub mod sharded_key;
19pub mod snap;
20pub mod storage_sharded_key;
21
22pub use accounts::*;
23pub use bal::*;
24pub use blocks::*;
25pub use integer_list::IntegerList;
26pub use metadata::*;
27pub use reth_db_models::{
28    AccountBeforeTx, ClientVersion, StaticFileBlockWithdrawals, StorageBeforeTx,
29    StoredBlockBodyIndices, StoredBlockWithdrawals,
30};
31pub use sharded_key::ShardedKey;
32pub use snap::*;
33
34/// Macro that implements [`Encode`] and [`Decode`] for uint types.
35macro_rules! impl_uints {
36    ($($name:tt),+) => {
37        $(
38            impl Encode for $name {
39                type Encoded = [u8; std::mem::size_of::<$name>()];
40
41                fn encode(self) -> Self::Encoded {
42                    self.to_be_bytes()
43                }
44            }
45
46            impl Decode for $name {
47                fn decode(value: &[u8]) -> Result<Self, $crate::DatabaseError> {
48                    Ok(
49                        $name::from_be_bytes(
50                            value.try_into().map_err(|_| $crate::DatabaseError::Decode)?
51                        )
52                    )
53                }
54            }
55        )+
56    };
57}
58
59impl_uints!(u64, u32, u16, u8);
60
61impl Encode for Vec<u8> {
62    type Encoded = Self;
63
64    fn encode(self) -> Self::Encoded {
65        self
66    }
67}
68
69impl Decode for Vec<u8> {
70    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
71        Ok(value.to_vec())
72    }
73
74    fn decode_owned(value: Vec<u8>) -> Result<Self, DatabaseError> {
75        Ok(value)
76    }
77}
78
79impl Encode for Address {
80    type Encoded = [u8; 20];
81
82    fn encode(self) -> Self::Encoded {
83        self.0 .0
84    }
85}
86
87impl Decode for Address {
88    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
89        Ok(Self::from_slice(value))
90    }
91}
92
93impl Encode for B256 {
94    type Encoded = [u8; 32];
95
96    fn encode(self) -> Self::Encoded {
97        self.0
98    }
99}
100
101impl Decode for B256 {
102    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
103        Ok(Self::new(value.try_into().map_err(|_| DatabaseError::Decode)?))
104    }
105}
106
107impl Encode for String {
108    type Encoded = Vec<u8>;
109
110    fn encode(self) -> Self::Encoded {
111        self.into_bytes()
112    }
113}
114
115impl Decode for String {
116    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
117        Self::decode_owned(value.to_vec())
118    }
119
120    fn decode_owned(value: Vec<u8>) -> Result<Self, DatabaseError> {
121        Self::from_utf8(value).map_err(|_| DatabaseError::Decode)
122    }
123}
124
125impl Encode for StoredNibbles {
126    type Encoded = arrayvec::ArrayVec<u8, 64>;
127
128    fn encode(self) -> Self::Encoded {
129        self.0.iter().collect()
130    }
131}
132
133impl Decode for StoredNibbles {
134    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
135        Ok(Self::from_compact(value, value.len()).0)
136    }
137}
138
139impl Encode for StoredNibblesSubKey {
140    type Encoded = [u8; 65];
141
142    fn encode(self) -> Self::Encoded {
143        self.to_compact_array()
144    }
145}
146
147impl Decode for StoredNibblesSubKey {
148    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
149        Ok(Self::from_compact(value, value.len()).0)
150    }
151}
152
153impl Encode for PackedStoredNibbles {
154    type Encoded = [u8; 33];
155
156    fn encode(self) -> Self::Encoded {
157        self.to_compact_array()
158    }
159}
160
161impl Decode for PackedStoredNibbles {
162    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
163        Ok(Self::from_compact(value, value.len()).0)
164    }
165}
166
167impl Encode for PackedStoredNibblesSubKey {
168    type Encoded = [u8; 33];
169
170    fn encode(self) -> Self::Encoded {
171        self.to_compact_array()
172    }
173}
174
175impl Decode for PackedStoredNibblesSubKey {
176    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
177        Ok(Self::from_compact(value, value.len()).0)
178    }
179}
180
181impl Encode for PruneSegment {
182    type Encoded = [u8; 1];
183
184    fn encode(self) -> Self::Encoded {
185        let mut buf = [0u8];
186        self.to_compact(&mut buf.as_mut());
187        buf
188    }
189}
190
191impl Decode for PruneSegment {
192    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
193        Ok(Self::from_compact(value, value.len()).0)
194    }
195}
196
197impl Encode for ClientVersion {
198    type Encoded = Vec<u8>;
199
200    // Delegate to the Compact implementation
201    fn encode(self) -> Self::Encoded {
202        let mut buf = vec![];
203        self.to_compact(&mut buf);
204        buf
205    }
206}
207
208impl Decode for ClientVersion {
209    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
210        Ok(Self::from_compact(value, value.len()).0)
211    }
212}
213
214impl_compression_for_compact!(StoredBlockOmmers<H>, CompactU256);
215
216/// Adds wrapper structs for some primitive types so they can use `StructFlags` from Compact, when
217/// used as pure table values.
218macro_rules! add_wrapper_struct {
219    ($(($name:tt, $wrapper:tt)),+) => {
220        $(
221            /// Wrapper struct so it can use `StructFlags` from Compact, when used as pure table values.
222            #[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, Compact)]
223            #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
224            #[add_arbitrary_tests(compact)]
225            pub struct $wrapper(pub $name);
226
227            impl From<$name> for $wrapper {
228                fn from(value: $name) -> Self {
229                    $wrapper(value)
230                }
231            }
232
233            impl From<$wrapper> for $name {
234                fn from(value: $wrapper) -> Self {
235                    value.0
236                }
237            }
238
239            impl std::ops::Deref for $wrapper {
240                type Target = $name;
241
242                fn deref(&self) -> &Self::Target {
243                    &self.0
244                }
245            }
246
247        )+
248    };
249}
250
251add_wrapper_struct!((U256, CompactU256));
252add_wrapper_struct!((u64, CompactU64));
253add_wrapper_struct!((ClientVersion, CompactClientVersion));
254
255#[cfg(test)]
256mod tests {
257    // each value in the database has an extra field named flags that encodes metadata about other
258    // fields in the value, e.g. offset and length.
259    //
260    // this check is to ensure we do not inadvertently add too many fields to a struct which would
261    // expand the flags field and break backwards compatibility
262    #[test]
263    fn test_ensure_backwards_compatibility() {
264        use super::*;
265        use reth_codecs::{test_utils::UnusedBits, validate_bitflag_backwards_compat};
266        use reth_primitives_traits::Account;
267        use reth_prune_types::{PruneCheckpoint, PruneMode, PruneSegment};
268        use reth_stages_types::{
269            AccountHashingCheckpoint, CheckpointBlockRange, EntitiesCheckpoint,
270            ExecutionCheckpoint, HeadersCheckpoint, IndexHistoryCheckpoint, StageCheckpoint,
271            StageUnitCheckpoint, StorageHashingCheckpoint,
272        };
273        assert_eq!(Account::bitflag_encoded_bytes(), 2);
274        assert_eq!(AccountHashingCheckpoint::bitflag_encoded_bytes(), 1);
275        assert_eq!(CheckpointBlockRange::bitflag_encoded_bytes(), 1);
276        assert_eq!(CompactClientVersion::bitflag_encoded_bytes(), 0);
277        assert_eq!(CompactU256::bitflag_encoded_bytes(), 1);
278        assert_eq!(CompactU64::bitflag_encoded_bytes(), 1);
279        assert_eq!(EntitiesCheckpoint::bitflag_encoded_bytes(), 1);
280        assert_eq!(ExecutionCheckpoint::bitflag_encoded_bytes(), 0);
281        assert_eq!(HeadersCheckpoint::bitflag_encoded_bytes(), 0);
282        assert_eq!(IndexHistoryCheckpoint::bitflag_encoded_bytes(), 0);
283        assert_eq!(PruneCheckpoint::bitflag_encoded_bytes(), 1);
284        assert_eq!(PruneMode::bitflag_encoded_bytes(), 1);
285        assert_eq!(PruneSegment::bitflag_encoded_bytes(), 1);
286        assert_eq!(StageCheckpoint::bitflag_encoded_bytes(), 1);
287        assert_eq!(StageUnitCheckpoint::bitflag_encoded_bytes(), 1);
288        assert_eq!(StoredBlockBodyIndices::bitflag_encoded_bytes(), 1);
289        assert_eq!(StoredBlockWithdrawals::bitflag_encoded_bytes(), 0);
290        assert_eq!(StorageHashingCheckpoint::bitflag_encoded_bytes(), 1);
291
292        validate_bitflag_backwards_compat!(Account, UnusedBits::NotZero);
293        validate_bitflag_backwards_compat!(AccountHashingCheckpoint, UnusedBits::NotZero);
294        validate_bitflag_backwards_compat!(CheckpointBlockRange, UnusedBits::Zero);
295        validate_bitflag_backwards_compat!(CompactClientVersion, UnusedBits::Zero);
296        validate_bitflag_backwards_compat!(CompactU256, UnusedBits::NotZero);
297        validate_bitflag_backwards_compat!(CompactU64, UnusedBits::NotZero);
298        validate_bitflag_backwards_compat!(EntitiesCheckpoint, UnusedBits::Zero);
299        validate_bitflag_backwards_compat!(ExecutionCheckpoint, UnusedBits::Zero);
300        validate_bitflag_backwards_compat!(HeadersCheckpoint, UnusedBits::Zero);
301        validate_bitflag_backwards_compat!(IndexHistoryCheckpoint, UnusedBits::Zero);
302        validate_bitflag_backwards_compat!(PruneCheckpoint, UnusedBits::NotZero);
303        validate_bitflag_backwards_compat!(PruneMode, UnusedBits::Zero);
304        validate_bitflag_backwards_compat!(PruneSegment, UnusedBits::Zero);
305        validate_bitflag_backwards_compat!(StageCheckpoint, UnusedBits::NotZero);
306        validate_bitflag_backwards_compat!(StageUnitCheckpoint, UnusedBits::Zero);
307        validate_bitflag_backwards_compat!(StoredBlockBodyIndices, UnusedBits::Zero);
308        validate_bitflag_backwards_compat!(StoredBlockWithdrawals, UnusedBits::Zero);
309        validate_bitflag_backwards_compat!(StorageHashingCheckpoint, UnusedBits::NotZero);
310    }
311}