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