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 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
35macro_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 fn encode(self) -> Self::Encoded {
131 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 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 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
193macro_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 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
279macro_rules! add_wrapper_struct {
282 ($(($name:tt, $wrapper:tt)),+) => {
283 $(
284 #[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 #[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}