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