1use 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
37macro_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 fn encode(self) -> Self::Encoded {
133 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 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 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
195macro_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 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
281macro_rules! add_wrapper_struct {
284 ($(($name:tt, $wrapper:tt)),+) => {
285 $(
286 #[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 #[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}