reth_db_api/models/
accounts.rs

1//! Account related models and types.
2
3use std::ops::{Range, RangeInclusive};
4
5use crate::{
6    impl_fixed_arbitrary,
7    table::{Decode, Encode},
8    DatabaseError,
9};
10use alloy_primitives::{Address, BlockNumber, StorageKey};
11use serde::{Deserialize, Serialize};
12
13/// [`BlockNumber`] concatenated with [`Address`].
14///
15/// Since it's used as a key, it isn't compressed when encoding it.
16#[derive(
17    Debug, Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd, Hash,
18)]
19pub struct BlockNumberAddress(pub (BlockNumber, Address));
20
21impl BlockNumberAddress {
22    /// Create a new Range from `start` to `end`
23    ///
24    /// Note: End is inclusive
25    pub fn range(range: RangeInclusive<BlockNumber>) -> Range<Self> {
26        (*range.start(), Address::ZERO).into()..(*range.end() + 1, Address::ZERO).into()
27    }
28
29    /// Return the block number
30    pub const fn block_number(&self) -> BlockNumber {
31        self.0 .0
32    }
33
34    /// Return the address
35    pub const fn address(&self) -> Address {
36        self.0 .1
37    }
38
39    /// Consumes `Self` and returns [`BlockNumber`], [`Address`]
40    pub const fn take(self) -> (BlockNumber, Address) {
41        (self.0 .0, self.0 .1)
42    }
43}
44
45impl From<(BlockNumber, Address)> for BlockNumberAddress {
46    fn from(tpl: (u64, Address)) -> Self {
47        Self(tpl)
48    }
49}
50
51impl Encode for BlockNumberAddress {
52    type Encoded = [u8; 28];
53
54    fn encode(self) -> Self::Encoded {
55        let block_number = self.0 .0;
56        let address = self.0 .1;
57
58        let mut buf = [0u8; 28];
59
60        buf[..8].copy_from_slice(&block_number.to_be_bytes());
61        buf[8..].copy_from_slice(address.as_slice());
62        buf
63    }
64}
65
66impl Decode for BlockNumberAddress {
67    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
68        let num = u64::from_be_bytes(value[..8].try_into().map_err(|_| DatabaseError::Decode)?);
69        let hash = Address::from_slice(&value[8..]);
70        Ok(Self((num, hash)))
71    }
72}
73
74/// [`Address`] concatenated with [`StorageKey`]. Used by `reth_etl` and history stages.
75///
76/// Since it's used as a key, it isn't compressed when encoding it.
77#[derive(
78    Debug, Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd, Hash,
79)]
80pub struct AddressStorageKey(pub (Address, StorageKey));
81
82impl Encode for AddressStorageKey {
83    type Encoded = [u8; 52];
84
85    fn encode(self) -> Self::Encoded {
86        let address = self.0 .0;
87        let storage_key = self.0 .1;
88
89        let mut buf = [0u8; 52];
90
91        buf[..20].copy_from_slice(address.as_slice());
92        buf[20..].copy_from_slice(storage_key.as_slice());
93        buf
94    }
95}
96
97impl Decode for AddressStorageKey {
98    fn decode(value: &[u8]) -> Result<Self, DatabaseError> {
99        let address = Address::from_slice(&value[..20]);
100        let storage_key = StorageKey::from_slice(&value[20..]);
101        Ok(Self((address, storage_key)))
102    }
103}
104
105impl_fixed_arbitrary!((BlockNumberAddress, 28), (AddressStorageKey, 52));
106
107#[cfg(test)]
108mod tests {
109    use super::*;
110    use rand::{rng, Rng};
111    use std::str::FromStr;
112
113    #[test]
114    fn test_block_number_address() {
115        let num = 1u64;
116        let hash = Address::from_str("ba5e000000000000000000000000000000000000").unwrap();
117        let key = BlockNumberAddress((num, hash));
118
119        let mut bytes = [0u8; 28];
120        bytes[..8].copy_from_slice(&num.to_be_bytes());
121        bytes[8..].copy_from_slice(hash.as_slice());
122
123        let encoded = Encode::encode(key);
124        assert_eq!(encoded, bytes);
125
126        let decoded: BlockNumberAddress = Decode::decode(&encoded).unwrap();
127        assert_eq!(decoded, key);
128    }
129
130    #[test]
131    fn test_block_number_address_rand() {
132        let mut bytes = [0u8; 28];
133        rng().fill(bytes.as_mut_slice());
134        let key = BlockNumberAddress::arbitrary(&mut Unstructured::new(&bytes)).unwrap();
135        assert_eq!(bytes, Encode::encode(key));
136    }
137
138    #[test]
139    fn test_address_storage_key() {
140        let storage_key = StorageKey::random();
141        let address = Address::from_str("ba5e000000000000000000000000000000000000").unwrap();
142        let key = AddressStorageKey((address, storage_key));
143
144        let mut bytes = [0u8; 52];
145        bytes[..20].copy_from_slice(address.as_slice());
146        bytes[20..].copy_from_slice(storage_key.as_slice());
147
148        let encoded = Encode::encode(key);
149        assert_eq!(encoded, bytes);
150
151        let decoded: AddressStorageKey = Decode::decode(&encoded).unwrap();
152        assert_eq!(decoded, key);
153    }
154
155    #[test]
156    fn test_address_storage_key_rand() {
157        let mut bytes = [0u8; 52];
158        rng().fill(bytes.as_mut_slice());
159        let key = AddressStorageKey::arbitrary(&mut Unstructured::new(&bytes)).unwrap();
160        assert_eq!(bytes, Encode::encode(key));
161    }
162}