1#[cfg(not(feature = "std"))]
2use alloc::{string::ToString, vec::Vec};
3use core::mem;
4
5use ethrex_crypto::Crypto;
6use ethrex_rlp::encode::RLPEncode;
7
8use crate::{
9 ValueRLP,
10 error::TrieError,
11 nibbles::Nibbles,
12 node::{BranchNode, NodeRemoveResult},
13 node_hash::NodeHash,
14};
15
16use super::{ExtensionNode, Node, ValueOrHash};
17#[derive(
20 Debug,
21 Clone,
22 Default,
23 PartialEq,
24 Eq,
25 serde::Serialize,
26 serde::Deserialize,
27 rkyv::Deserialize,
28 rkyv::Serialize,
29 rkyv::Archive,
30)]
31pub struct LeafNode {
32 pub partial: Nibbles,
33 pub value: ValueRLP,
34}
35
36impl LeafNode {
37 pub const fn new(partial: Nibbles, value: ValueRLP) -> Self {
39 Self { partial, value }
40 }
41
42 pub fn get(&self, path: Nibbles) -> Result<Option<ValueRLP>, TrieError> {
44 if self.partial == path {
45 Ok(Some(self.value.clone()))
46 } else {
47 Ok(None)
48 }
49 }
50
51 pub fn insert(&mut self, path: Nibbles, value: ValueOrHash) -> Result<Option<Node>, TrieError> {
53 if self.partial == path {
61 match value {
62 ValueOrHash::Value(value) => self.value = value,
63 ValueOrHash::Hash(_) => {
64 return Err(TrieError::Verify(
65 "attempt to override proof node with external hash".to_string(),
66 ));
67 }
68 }
69 Ok(None)
70 } else {
71 let match_index = path.count_prefix(&self.partial);
72 let self_choice_idx = self.partial.at(match_index);
73 let new_leaf_choice_idx = path.at(match_index);
74 self.partial = self.partial.offset(match_index + 1);
75
76 let branch_node = if self_choice_idx == 16 {
77 let mut choices = BranchNode::EMPTY_CHOICES;
81 choices[new_leaf_choice_idx] = match value {
82 ValueOrHash::Value(value) => {
83 Node::from(LeafNode::new(path.offset(match_index + 1), value)).into()
84 }
85 ValueOrHash::Hash(hash) => hash.into(),
86 };
87 BranchNode::new_with_value(choices, mem::take(&mut self.value))
88 } else if new_leaf_choice_idx == 16 {
89 let mut choices = BranchNode::EMPTY_CHOICES;
92 let child: Node = self.take().into();
93 choices[self_choice_idx] = child.into();
94 BranchNode::new_with_value(
95 choices,
96 match value {
97 ValueOrHash::Value(value) => value,
98 ValueOrHash::Hash(_) => todo!("handle override case (error?)"),
100 },
101 )
102 } else {
103 let mut choices = BranchNode::EMPTY_CHOICES;
107 choices[new_leaf_choice_idx] = match value {
108 ValueOrHash::Value(value) => {
109 Node::from(LeafNode::new(path.offset(match_index + 1), value)).into()
110 }
111 ValueOrHash::Hash(hash) => hash.into(),
112 };
113 let child: Node = self.take().into();
114 choices[self_choice_idx] = child.into();
115 BranchNode::new(choices)
116 };
117
118 let final_node = if match_index == 0 {
119 branch_node.into()
120 } else {
121 ExtensionNode::new(path.slice(0, match_index), Node::from(branch_node).into())
124 .into()
125 };
126
127 Ok(Some(final_node))
128 }
129 }
130
131 pub fn remove(
133 &mut self,
134 path: Nibbles,
135 ) -> Result<(Option<NodeRemoveResult>, Option<ValueRLP>), TrieError> {
136 Ok(if self.partial == path {
137 (None, Some(mem::take(&mut self.value)))
138 } else {
139 (Some(NodeRemoveResult::Mutated), None)
140 })
141 }
142
143 pub fn compute_hash(&self, crypto: &dyn Crypto) -> NodeHash {
145 self.compute_hash_no_alloc(&mut vec![], crypto)
146 }
147
148 pub fn compute_hash_no_alloc(&self, buf: &mut Vec<u8>, crypto: &dyn Crypto) -> NodeHash {
150 buf.clear();
151 self.encode(buf);
152 let hash = NodeHash::from_encoded(buf, crypto);
153 buf.clear();
154 hash
155 }
156
157 pub fn get_path(&self, node_path: &mut Vec<Vec<u8>>) -> Result<(), TrieError> {
159 let encoded = self.encode_to_vec();
160 if encoded.len() >= 32 {
161 node_path.push(encoded);
162 }
163 Ok(())
164 }
165
166 pub fn take(&mut self) -> Self {
170 LeafNode {
171 partial: self.partial.take(),
172 value: mem::take(&mut self.value),
173 }
174 }
175}
176
177#[cfg(test)]
178mod test {
179 use ethrex_crypto::NativeCrypto;
180 use ethrex_rlp::{decode::RLPDecode, encode::RLPEncode};
181
182 use super::*;
183 use crate::{Trie, pmt_node};
184
185 #[test]
186 fn new() {
187 let node = LeafNode::new(Default::default(), Default::default());
188 assert_eq!(node.value, ValueRLP::default());
189 }
190
191 #[test]
192 fn get_some() {
193 let node = pmt_node! { @(trie)
194 leaf { vec![1, 2, 16] => vec![0x12, 0x34, 0x56, 0x78] }
195 };
196
197 assert_eq!(
198 node.get(Nibbles::from_bytes(&[0x12])).unwrap(),
199 Some(vec![0x12, 0x34, 0x56, 0x78]),
200 );
201 }
202
203 #[test]
204 fn get_none() {
205 let node = pmt_node! { @(trie)
206 leaf { vec![1,2,16] => vec![0x12, 0x34, 0x56, 0x78] }
207 };
208
209 assert!(node.get(Nibbles::from_bytes(&[0x34])).unwrap().is_none());
210 }
211
212 #[test]
213 fn insert_replace() {
214 let mut node = pmt_node! { @(trie)
215 leaf { vec![1,2,16] => vec![0x12, 0x34, 0x56, 0x78] }
216 };
217
218 assert!(
219 node.insert(Nibbles::from_bytes(&[0x12]), vec![0x13].into())
220 .unwrap()
221 .is_none()
222 );
223
224 assert_eq!(node.value, vec![0x13]);
225 }
226
227 #[test]
228 fn insert_branch() {
229 let trie = Trie::new_temp();
230 let mut node = pmt_node! { @(trie)
231 leaf { vec![1,2,16] => vec![0x12, 0x34, 0x56, 0x78] }
232 };
233 let path = Nibbles::from_bytes(&[0x22]);
234 let value = vec![0x23];
235 let node = node.insert(path.clone(), value.clone().into()).unwrap();
236 let node = match node {
237 Some(Node::Branch(x)) => x,
238 _ => panic!("expected a branch node"),
239 };
240 assert_eq!(node.get(trie.db.as_ref(), path).unwrap(), Some(value));
241 }
242
243 #[test]
244 fn insert_extension_branch() {
245 let trie = Trie::new_temp();
246 let mut node = pmt_node! { @(trie)
247 leaf { vec![1,2,16] => vec![0x12, 0x34, 0x56, 0x78] }
248 };
249
250 let path = Nibbles::from_bytes(&[0x13]);
251 let value = vec![0x15];
252
253 let node = node.insert(path.clone(), value.clone().into()).unwrap();
254
255 assert!(matches!(node, Some(Node::Extension(_))));
256 assert_eq!(
257 node.unwrap().get(trie.db.as_ref(), path).unwrap(),
258 Some(value)
259 );
260 }
261
262 #[test]
263 fn insert_extension_branch_value_self() {
264 let trie = Trie::new_temp();
265 let mut node = pmt_node! { @(trie)
266 leaf { vec![1,2,16] => vec![0x12, 0x34, 0x56, 0x78] }
267 };
268
269 let path = Nibbles::from_bytes(&[0x12, 0x34]);
270 let value = vec![0x17];
271
272 let node = node.insert(path.clone(), value.clone().into()).unwrap();
273
274 assert!(matches!(node, Some(Node::Extension(_))));
275 assert_eq!(
276 node.unwrap().get(trie.db.as_ref(), path).unwrap(),
277 Some(value)
278 );
279 }
280
281 #[test]
282 fn insert_extension_branch_value_other() {
283 let trie = Trie::new_temp();
284 let mut node = pmt_node! { @(trie)
285 leaf { vec![1, 2, 3, 4, 16] => vec![0x12, 0x34, 0x56, 0x78] }
286 };
287
288 let path = Nibbles::from_bytes(&[0x12]);
289 let value = vec![0x17];
290
291 let node = node.insert(path.clone(), value.clone().into()).unwrap();
292
293 assert!(matches!(node, Some(Node::Extension(_))));
294 assert_eq!(
295 node.unwrap().get(trie.db.as_ref(), path).unwrap(),
296 Some(value)
297 );
298 }
299
300 #[test]
309 fn remove_self() {
310 let mut node = LeafNode::new(
311 Nibbles::from_bytes(&[0x12, 0x34]),
312 vec![0x12, 0x34, 0x56, 0x78],
313 );
314 let (node, value) = node.remove(Nibbles::from_bytes(&[0x12, 0x34])).unwrap();
315
316 assert!(node.is_none());
317 assert_eq!(value, Some(vec![0x12, 0x34, 0x56, 0x78]));
318 }
319
320 #[test]
321 fn remove_none() {
322 let mut node = LeafNode::new(
323 Nibbles::from_bytes(&[0x12, 0x34]),
324 vec![0x12, 0x34, 0x56, 0x78],
325 );
326
327 let (node, value) = node.remove(Nibbles::from_bytes(&[0x12])).unwrap();
328
329 assert!(node.is_some());
330 assert_eq!(value, None);
331 }
332
333 #[test]
334 fn compute_hash_x() {
335 let node = LeafNode::new(Nibbles::from_bytes(b"key".as_ref()), b"value".to_vec());
336 let node_hash_ref = node.compute_hash(&NativeCrypto);
337 assert_eq!(
338 node_hash_ref.as_ref(),
339 &[
340 0xCB, 0x84, 0x20, 0x6B, 0x65, 0x79, 0x85, 0x76, 0x61, 0x6C, 0x75, 0x65
341 ],
342 );
343 }
344
345 #[test]
346 fn compute_hash_long() {
347 let node = LeafNode::new(
348 Nibbles::from_bytes(b"key".as_ref()),
349 b"a comparatively long value".to_vec(),
350 );
351
352 let node_hash_ref = node.compute_hash(&NativeCrypto);
353 assert_eq!(
354 node_hash_ref.as_ref(),
355 &[
356 0xEB, 0x92, 0x75, 0xB3, 0xAE, 0x09, 0x3A, 0x17, 0x75, 0x7C, 0xFB, 0x42, 0xF7, 0xD5,
357 0x57, 0xF9, 0xE5, 0x77, 0xBD, 0x5B, 0xEB, 0x86, 0xA8, 0x68, 0x49, 0x91, 0xA6, 0x5B,
358 0x87, 0x5F, 0x80, 0x7A,
359 ],
360 );
361 }
362
363 #[test]
364 fn symmetric_encoding_a() {
365 let node: Node = LeafNode::new(
366 Nibbles::from_bytes(b"key".as_ref()),
367 b"a comparatively long value".to_vec(),
368 )
369 .into();
370 assert_eq!(Node::decode(&node.encode_to_vec()).unwrap(), node)
371 }
372
373 #[test]
374 fn symmetric_encoding_b() {
375 let node: Node = LeafNode::new(
376 Nibbles::from_bytes(&[0x12, 0x34]),
377 vec![0x12, 0x34, 0x56, 0x78],
378 )
379 .into();
380 assert_eq!(Node::decode(&node.encode_to_vec()).unwrap(), node)
381 }
382
383 #[test]
384 fn symmetric_encoding_c() {
385 let node: Node = LeafNode::new(
386 Nibbles::from_bytes(&[]),
387 vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 20],
388 )
389 .into();
390 assert_eq!(Node::decode(&node.encode_to_vec()).unwrap(), node)
391 }
392}