1use ethereum_types::H256;
2use ethrex_crypto::Crypto;
3use ethrex_rlp::{decode::RLPDecode, encode::RLPEncode, error::RLPDecodeError, structs::Encoder};
4
5use crate::rkyv_utils::H256Wrapper;
6
7#[derive(
12 Debug,
13 Clone,
14 Copy,
15 PartialEq,
16 Hash,
17 PartialOrd,
18 Ord,
19 Eq,
20 serde::Serialize,
21 serde::Deserialize,
22 rkyv::Serialize,
23 rkyv::Deserialize,
24 rkyv::Archive,
25)]
26pub enum NodeHash {
27 Hashed(#[rkyv(with=H256Wrapper)] H256),
28 Inline(([u8; 31], u8)),
30}
31
32impl AsRef<[u8]> for NodeHash {
33 fn as_ref(&self) -> &[u8] {
34 match self {
35 NodeHash::Inline((slice, len)) => &slice[0..(*len as usize)],
36 NodeHash::Hashed(x) => x.as_bytes(),
37 }
38 }
39}
40
41impl NodeHash {
42 pub fn from_encoded(encoded: &[u8], crypto: &dyn Crypto) -> NodeHash {
44 if encoded.len() >= 32 {
45 let hash = crypto.keccak256(encoded);
46 NodeHash::Hashed(H256::from_slice(&hash))
47 } else {
48 NodeHash::from_slice(encoded)
49 }
50 }
51
52 pub(crate) fn from_slice(slice: &[u8]) -> NodeHash {
56 match slice.len() {
57 0..32 => {
58 let mut buffer = [0; 31];
59 buffer[0..slice.len()].copy_from_slice(slice);
60 NodeHash::Inline((buffer, slice.len() as u8))
61 }
62 _ => NodeHash::Hashed(H256::from_slice(slice)),
63 }
64 }
65
66 pub fn finalize(self, crypto: &dyn Crypto) -> H256 {
69 match self {
70 NodeHash::Inline(_) => H256(crypto.keccak256(self.as_ref())),
71 NodeHash::Hashed(x) => x,
72 }
73 }
74
75 pub fn is_valid(&self) -> bool {
79 !matches!(self, NodeHash::Inline(v) if v.1 == 0)
80 }
81
82 pub fn encode<'a>(&self, mut encoder: Encoder<'a>) -> Encoder<'a> {
84 match self {
85 NodeHash::Inline(_) => {
86 encoder = encoder.encode_raw(self.as_ref());
87 }
88 NodeHash::Hashed(_) => {
89 encoder = encoder.encode_bytes(self.as_ref());
90 }
91 }
92 encoder
93 }
94
95 pub fn len(&self) -> usize {
96 match self {
97 NodeHash::Hashed(h256) => h256.as_bytes().len(),
98 NodeHash::Inline(value) => value.1 as usize,
99 }
100 }
101
102 pub fn is_empty(&self) -> bool {
103 match self {
104 NodeHash::Hashed(h256) => h256.as_bytes().is_empty(),
105 NodeHash::Inline(value) => value.1 == 0,
106 }
107 }
108}
109
110impl From<H256> for NodeHash {
111 fn from(value: H256) -> Self {
112 NodeHash::Hashed(value)
113 }
114}
115
116impl From<NodeHash> for Vec<u8> {
117 fn from(val: NodeHash) -> Self {
118 val.as_ref().to_vec()
119 }
120}
121
122impl From<&NodeHash> for Vec<u8> {
123 fn from(val: &NodeHash) -> Self {
124 val.as_ref().to_vec()
125 }
126}
127
128impl Default for NodeHash {
129 fn default() -> Self {
130 NodeHash::Inline(([0; 31], 0))
131 }
132}
133
134impl RLPEncode for NodeHash {
136 fn encode(&self, buf: &mut dyn bytes::BufMut) {
137 RLPEncode::encode(&Into::<Vec<u8>>::into(self), buf)
138 }
139
140 fn length(&self) -> usize {
141 match self {
142 NodeHash::Hashed(_) => 33, NodeHash::Inline((_, 0)) => 1, NodeHash::Inline((_, len)) => *len as usize, }
146 }
147}
148
149impl RLPDecode for NodeHash {
150 fn decode_unfinished(rlp: &[u8]) -> Result<(Self, &[u8]), ethrex_rlp::error::RLPDecodeError> {
151 let (hash, rest): (Vec<u8>, &[u8]);
152 (hash, rest) = RLPDecode::decode_unfinished(rlp)?;
153 if hash.len() > 32 {
154 return Err(RLPDecodeError::InvalidLength);
155 }
156 let hash = NodeHash::from_slice(&hash);
157 Ok((hash, rest))
158 }
159}