1use crate::{EMPTY_ROOT_HASH, KECCAK_EMPTY};
2use alloy_primitives::{keccak256, B256, U256};
3use alloy_rlp::{RlpDecodable, RlpEncodable};
4
5#[derive(Copy, Clone, Debug, PartialEq, Eq, RlpDecodable, RlpEncodable)]
7#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
10pub struct TrieAccount {
11 #[cfg_attr(feature = "serde", serde(with = "quantity"))]
13 pub nonce: u64,
14 pub balance: U256,
16 pub storage_root: B256,
18 pub code_hash: B256,
20}
21
22impl Default for TrieAccount {
23 fn default() -> Self {
24 Self {
25 nonce: 0,
26 balance: U256::ZERO,
27 storage_root: EMPTY_ROOT_HASH,
28 code_hash: KECCAK_EMPTY,
29 }
30 }
31}
32
33impl TrieAccount {
34 pub fn trie_hash_slow(&self) -> B256 {
36 keccak256(alloy_rlp::encode(self))
37 }
38}
39
40#[cfg(feature = "serde")]
41mod quantity {
42 use alloy_primitives::U64;
43 use serde::{Deserialize, Deserializer, Serialize, Serializer};
44
45 pub(crate) fn serialize<S>(value: &u64, serializer: S) -> Result<S::Ok, S::Error>
47 where
48 S: Serializer,
49 {
50 U64::from(*value).serialize(serializer)
51 }
52
53 pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<u64, D::Error>
55 where
56 D: Deserializer<'de>,
57 {
58 U64::deserialize(deserializer).map(|value| value.to())
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65 use alloy_primitives::{hex, U256};
66 use alloy_rlp::Decodable;
67
68 #[test]
69 fn test_account_encoding() {
70 let account = TrieAccount {
71 nonce: 1,
72 balance: U256::from(1000),
73 storage_root: B256::from_slice(&hex!(
74 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
75 )),
76 code_hash: keccak256(hex!("5a465a905090036002900360015500")),
77 };
78
79 let encoded = alloy_rlp::encode(account);
80
81 let decoded = TrieAccount::decode(&mut &encoded[..]).unwrap();
82 assert_eq!(account, decoded);
83 }
84
85 #[test]
86 fn test_trie_hash_slow() {
87 let account = TrieAccount {
88 nonce: 1,
89 balance: U256::from(1000),
90 storage_root: B256::from_slice(&hex!(
91 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
92 )),
93 code_hash: keccak256(hex!("5a465a905090036002900360015500")),
94 };
95
96 let expected_hash = keccak256(alloy_rlp::encode(account));
97 let actual_hash = account.trie_hash_slow();
98 assert_eq!(expected_hash, actual_hash);
99 }
100}