1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
use std::collections::HashMap; use crate::{ merkle::{ empty_nodes, nibble::{self, Nibble, NibbleVec}, MerkleNode, MerkleValue, }, Change, }; fn make_submap<'a, 'b: 'a, T: Iterator<Item = (&'a NibbleVec, &'a &'b [u8])>>( common_len: usize, map: T, ) -> HashMap<NibbleVec, &'b [u8]> { let mut submap = HashMap::new(); for (key, &value) in map { submap.insert(key[common_len..].into(), value); } submap } pub fn build_value(node: MerkleNode<'_>) -> (MerkleValue<'_>, Change) { let mut change = Change::default(); let value = change.add_value(&node); (value, change) } pub fn build_node<'a>(map: &HashMap<NibbleVec, &'a [u8]>) -> (MerkleNode<'a>, Change) { let mut change = Change::default(); assert!(!map.is_empty()); if map.len() == 1 { let key = map.keys().next().unwrap(); return (MerkleNode::Leaf(key.clone(), map.get(key).unwrap()), change); } debug_assert!(map.len() > 1); let common = nibble::common_all(map.keys().map(|v| v.as_ref())); if !common.is_empty() { let submap = make_submap(common.len(), map.iter()); debug_assert!(!submap.is_empty()); let (node, subchange) = build_node(&submap); change.merge(&subchange); let (value, subchange) = build_value(node); change.merge(&subchange); (MerkleNode::Extension(common.into(), value), change) } else { let mut nodes: [MerkleValue<'_>; 16] = empty_nodes(); for (i, node) in nodes.iter_mut().enumerate() { let nibble = Nibble::from(i); let submap = make_submap( 1, map.iter() .filter(|&(key, _value)| !key.is_empty() && key[0] == nibble), ); if !submap.is_empty() { let (sub_node, subchange) = build_node(&submap); change.merge(&subchange); let (value, subchange) = build_value(sub_node); change.merge(&subchange); *node = value; } } let additional = map .iter() .find(|&(key, _value)| key.is_empty()) .map(|(_key, value)| *value); (MerkleNode::Branch(nodes, additional), change) } }