reth_db_api/models/
accounts.rs

1//! Account related models and types.
2
3use crate::{
4    impl_fixed_arbitrary,
5    table::{Decode, Encode},
6    DatabaseError,
7};
8use alloy_primitives::{Address, BlockNumber, StorageKey, B256};
9use serde::{Deserialize, Serialize};
10use std::ops::{Bound, Range, RangeBounds, RangeInclusive};
11
12/// [`BlockNumber`] concatenated with [`Address`].
13///
14/// Since it's used as a key, it isn't compressed when encoding it.
15#[derive(
16    Debug, Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd, Hash,
17)]
18pub struct BlockNumberAddress(pub (BlockNumber, Address));
19
20impl BlockNumberAddress {
21    /// Create a new Range from `start` to `end`
22    ///
23    /// Note: End is inclusive
24    pub fn range(range: RangeInclusive<BlockNumber>) -> Range<Self> {
25        (*range.start(), Address::ZERO).into()..(*range.end() + 1, Address::ZERO).into()
26    }
27
28    /// Return the block number
29    pub const fn block_number(&self) -> BlockNumber {
30        self.0 .0
31    }
32
33    /// Return the address
34    pub const fn address(&self) -> Address {
35        self.0 .1
36    }
37
38    /// Consumes `Self` and returns [`BlockNumber`], [`Address`]
39    pub const fn take(self) -> (BlockNumber, Address) {
40        (self.0 .0, self.0 .1)
41    }
42}
43
44impl From<(BlockNumber, Address)> for BlockNumberAddress {
45    fn from(tpl: (u64, Address)) -> Self {
46        Self(tpl)
47    }
48}
49
50impl Encode for BlockNumberAddress {
51    type Encoded = [u8; 28];
52
53    fn encode(self) -> Self::Encoded {
54        let block_number = self.0 .0;
55        let address = self.0 .1;
56
57        let mut buf = [0u8; 28];
58
59        buf[..8].copy_from_slice(&block_number.to_be_bytes());
60        buf[8..].copy_from_slice(address.as_slice());
61        buf
62    }
63}
64
65impl Decode for BlockNumberAddress {
66    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
67        let num = u64::from_be_bytes(value[..8].try_into().map_err(|_| DatabaseError::Decode)?);
68        let hash = Address::from_slice(&value[8..]);
69        Ok(Self((num, hash)))
70    }
71}
72
73/// A [`RangeBounds`] over a range of [`BlockNumberAddress`]s. Used to conveniently convert from a
74/// range of [`BlockNumber`]s.
75#[derive(Debug)]
76pub struct BlockNumberAddressRange {
77    /// Starting bound of the range.
78    pub start: Bound<BlockNumberAddress>,
79    /// Ending bound of the range.
80    pub end: Bound<BlockNumberAddress>,
81}
82
83impl RangeBounds<BlockNumberAddress> for BlockNumberAddressRange {
84    fn start_bound(&self) -> Bound<&BlockNumberAddress> {
85        self.start.as_ref()
86    }
87
88    fn end_bound(&self) -> Bound<&BlockNumberAddress> {
89        self.end.as_ref()
90    }
91}
92
93impl<R: RangeBounds<BlockNumber>> From<R> for BlockNumberAddressRange {
94    fn from(r: R) -> Self {
95        let start = match r.start_bound() {
96            Bound::Included(n) => Bound::Included(BlockNumberAddress((*n, Address::ZERO))),
97            Bound::Excluded(n) => Bound::Included(BlockNumberAddress((n + 1, Address::ZERO))),
98            Bound::Unbounded => Bound::Unbounded,
99        };
100
101        let end = match r.end_bound() {
102            Bound::Included(n) => Bound::Excluded(BlockNumberAddress((n + 1, Address::ZERO))),
103            Bound::Excluded(n) => Bound::Excluded(BlockNumberAddress((*n, Address::ZERO))),
104            Bound::Unbounded => Bound::Unbounded,
105        };
106
107        Self { start, end }
108    }
109}
110
111/// [`BlockNumber`] concatenated with [`B256`] (hashed address).
112///
113/// Since it's used as a key, it isn't compressed when encoding it.
114#[derive(
115    Debug, Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd, Hash,
116)]
117pub struct BlockNumberHashedAddress(pub (BlockNumber, B256));
118
119impl From<(BlockNumber, B256)> for BlockNumberHashedAddress {
120    fn from(tpl: (BlockNumber, B256)) -> Self {
121        Self(tpl)
122    }
123}
124
125impl Encode for BlockNumberHashedAddress {
126    type Encoded = [u8; 40];
127
128    fn encode(self) -> Self::Encoded {
129        let block_number = self.0 .0;
130        let hashed_address = self.0 .1;
131
132        let mut buf = [0u8; 40];
133
134        buf[..8].copy_from_slice(&block_number.to_be_bytes());
135        buf[8..].copy_from_slice(hashed_address.as_slice());
136        buf
137    }
138}
139
140impl Decode for BlockNumberHashedAddress {
141    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
142        let num = u64::from_be_bytes(value[..8].try_into().map_err(|_| DatabaseError::Decode)?);
143        let hash = B256::from_slice(&value[8..]);
144        Ok(Self((num, hash)))
145    }
146}
147
148/// [`Address`] concatenated with [`StorageKey`]. Used by `reth_etl` and history stages.
149///
150/// Since it's used as a key, it isn't compressed when encoding it.
151#[derive(
152    Debug, Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd, Hash,
153)]
154pub struct AddressStorageKey(pub (Address, StorageKey));
155
156impl Encode for AddressStorageKey {
157    type Encoded = [u8; 52];
158
159    fn encode(self) -> Self::Encoded {
160        let address = self.0 .0;
161        let storage_key = self.0 .1;
162
163        let mut buf = [0u8; 52];
164
165        buf[..20].copy_from_slice(address.as_slice());
166        buf[20..].copy_from_slice(storage_key.as_slice());
167        buf
168    }
169}
170
171impl Decode for AddressStorageKey {
172    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
173        let address = Address::from_slice(&value[..20]);
174        let storage_key = StorageKey::from_slice(&value[20..]);
175        Ok(Self((address, storage_key)))
176    }
177}
178
179impl_fixed_arbitrary!((BlockNumberAddress, 28), (AddressStorageKey, 52));
180
181#[cfg(test)]
182mod tests {
183    use super::*;
184    use alloy_primitives::address;
185    use rand::{rng, Rng};
186
187    #[test]
188    fn test_block_number_address() {
189        let num = 1u64;
190        let hash = address!("0xba5e000000000000000000000000000000000000");
191        let key = BlockNumberAddress((num, hash));
192
193        let mut bytes = [0u8; 28];
194        bytes[..8].copy_from_slice(&num.to_be_bytes());
195        bytes[8..].copy_from_slice(hash.as_slice());
196
197        let encoded = Encode::encode(key);
198        assert_eq!(encoded, bytes);
199
200        let decoded: BlockNumberAddress = Decode::decode(&encoded).unwrap();
201        assert_eq!(decoded, key);
202    }
203
204    #[test]
205    fn test_block_number_address_rand() {
206        let mut bytes = [0u8; 28];
207        rng().fill(bytes.as_mut_slice());
208        let key = BlockNumberAddress::arbitrary(&mut Unstructured::new(&bytes)).unwrap();
209        assert_eq!(bytes, Encode::encode(key));
210    }
211
212    #[test]
213    fn test_address_storage_key() {
214        let storage_key = StorageKey::random();
215        let address = address!("0xba5e000000000000000000000000000000000000");
216        let key = AddressStorageKey((address, storage_key));
217
218        let mut bytes = [0u8; 52];
219        bytes[..20].copy_from_slice(address.as_slice());
220        bytes[20..].copy_from_slice(storage_key.as_slice());
221
222        let encoded = Encode::encode(key);
223        assert_eq!(encoded, bytes);
224
225        let decoded: AddressStorageKey = Decode::decode(&encoded).unwrap();
226        assert_eq!(decoded, key);
227    }
228
229    #[test]
230    fn test_address_storage_key_rand() {
231        let mut bytes = [0u8; 52];
232        rng().fill(bytes.as_mut_slice());
233        let key = AddressStorageKey::arbitrary(&mut Unstructured::new(&bytes)).unwrap();
234        assert_eq!(bytes, Encode::encode(key));
235    }
236}