From 0e84b1172e59c640620e1fd5d8770ca8eb16ffd8 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Sun, 7 Jul 2019 16:54:27 +0200 Subject: [PATCH] update & some fixes & travis --- .travis.yml | 9 + README.md | 4 +- src/lib.rs | 502 +++++++++++++++++++++++++++------------------------ src/utils.rs | 11 +- 4 files changed, 287 insertions(+), 239 deletions(-) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..9f108b7 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +language: rust +rust: +- stable + +cache: +- cargo + +script: +- RUST_BACKTRACE=1 cargo test --all diff --git a/README.md b/README.md index 5ec5a4f..3d3ed52 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ -# merkletree-rs +# merkletree-rs [![Build Status](https://travis-ci.org/arnaucube/merkletree-rs.svg?branch=master)](https://travis-ci.org/arnaucube/merkletree-rs) Sparse MerkleTree implementation in Rust. The MerkleTree is optimized in the design and concepts, to have a faster and lighter MerkleTree, maintaining compatibility with a non optimized MerkleTree. In this way, the MerkleRoot of the optimized MerkleTree will be the same that the MerkleRoot of the non optimized MerkleTree. +Compatible with the Go version: https://github.com/arnaucube/go-merkletree + ## Usage Create new tree: diff --git a/src/lib.rs b/src/lib.rs index 13e557d..824ee6c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,8 @@ extern crate rustc_hex; extern crate hex; +use rustc_hex::ToHex; + mod utils; mod node; @@ -48,12 +50,12 @@ pub struct Db { storage: HashMap<[u8;32], Vec>, } impl Db { - pub fn insert(&mut self, k: [u8; 32], t: u8, il: u32, b: &mut Vec) { + pub fn insert(&mut self, k: [u8; 32], t: u8, il: u32, b: Vec) { let mut v: Vec; v = [t].to_vec(); let il_bytes = il.to_le_bytes(); - v.append(&mut il_bytes.to_vec()); // il_bytes are [u8;4] (4 bytes) - v.append(b); + v.extend(il_bytes.to_vec()); // il_bytes are [u8;4] (4 bytes) + v.extend(&b); self.storage.insert(k, v); } pub fn get(&self, k: &[u8;32]) -> (u8, u32, Vec) { @@ -102,9 +104,9 @@ impl MerkleTree { #![allow(unused_variables)] #[allow(dead_code)] - // println!("adding value: {:?}", v.bytes()); + let leaf_node_string = String::from_utf8_lossy(&v.bytes()); // add the leaf that we are adding - self.sto.insert(v.ht(), TYPENODEVALUE, v.index_length(), &mut v.bytes().to_vec()); + self.sto.insert(v.ht(), TYPENODEVALUE, v.index_length(), v.bytes().to_vec()); let index = v.index_length() as usize; let hi = v.hi(); @@ -123,13 +125,14 @@ impl MerkleTree { let path_child = utils::get_path(self.num_levels, hi_child); let pos_diff = utils::compare_paths(&path_child, &path); if pos_diff == 999 { // TODO use a match here, and instead of 999 return something better + println!("node already exists"); println!("compare paths err"); return; } let final_node_1_hash = utils::calc_hash_from_leaf_and_level(pos_diff, &path_child, utils::hash_vec(node_bytes.to_vec())); - self.sto.insert(final_node_1_hash, TYPENODEFINAL, il, &mut node_bytes.to_vec()); + self.sto.insert(final_node_1_hash, TYPENODEFINAL, il, node_bytes.to_vec()); let final_node_2_hash = utils::calc_hash_from_leaf_and_level(pos_diff, &path, v.ht()); - self.sto.insert(final_node_2_hash, TYPENODEFINAL, v.index_length(), &mut v.bytes().to_vec()); + self.sto.insert(final_node_2_hash, TYPENODEFINAL, v.index_length(), v.bytes().to_vec()); // parent node let parent_node: node::TreeNode; @@ -138,24 +141,25 @@ impl MerkleTree { child_l: final_node_1_hash, child_r: final_node_2_hash, }} else { - parent_node = node::TreeNode { - child_l: final_node_2_hash, - child_r: final_node_1_hash, - }} + parent_node = node::TreeNode { + child_l: final_node_2_hash, + child_r: final_node_1_hash, + }} let empties = utils::get_empties_between_i_and_pos(i, pos_diff+1); for empty in &empties { siblings.push(*empty); } - let path_from_pos_diff = utils::cut_path(&path, (pos_diff +1) as usize); - self.root = self.replace_leaf(path_from_pos_diff, siblings.clone(), parent_node.ht(), TYPENODENORMAL, 0, &mut parent_node.bytes().to_vec()); + let path_from_pos_diff = utils::cut_path(&path, (pos_diff + 1) as usize); + + self.root = self.replace_leaf(path_from_pos_diff, &siblings, parent_node.ht(), TYPENODENORMAL, 0, parent_node.bytes().to_vec()); return; } let node = node::parse_node_bytes(node_bytes); let sibling: [u8;32]; - if path[i as usize] { + if !path[i as usize] { node_hash = node.child_l; sibling = node.child_r; } else { @@ -166,38 +170,38 @@ impl MerkleTree { if node_hash == EMPTYNODEVALUE { if i==self.num_levels-2 && siblings[siblings.len()-1]==EMPTYNODEVALUE { let final_node_hash = utils::calc_hash_from_leaf_and_level(i+1, &path, v.ht()); - self.sto.insert(final_node_hash, TYPENODEFINAL, v.index_length(), &mut v.bytes().to_vec()); + self.sto.insert(final_node_hash, TYPENODEFINAL, v.index_length(), v.bytes().to_vec()); self.root = final_node_hash; return; } let final_node_hash = utils::calc_hash_from_leaf_and_level(i, &path, v.ht()); let path_from_i = utils::cut_path(&path, i as usize); - self.root = self.replace_leaf(path_from_i, siblings.clone(), final_node_hash, TYPENODEFINAL, v.index_length(), &mut v.bytes().to_vec()); + self.root = self.replace_leaf(path_from_i, &siblings, final_node_hash, TYPENODEFINAL, v.index_length(), v.bytes().to_vec()); return; } } - self.root = self.replace_leaf(path, siblings, v.ht(), TYPENODEVALUE, v.index_length(), &mut v.bytes().to_vec()); + self.root = self.replace_leaf(path, &siblings, v.ht(), TYPENODEVALUE, v.index_length(), v.bytes().to_vec()); } #[allow(dead_code)] - pub fn replace_leaf(&mut self, path: Vec, siblings: Vec<[u8;32]>, leaf_hash: [u8;32], node_type: u8, index_length: u32, leaf_value: &mut Vec) -> [u8;32] { + pub fn replace_leaf(&mut self, path: Vec, siblings: &Vec<[u8;32]>, leaf_hash: [u8;32], node_type: u8, index_length: u32, leaf_value: Vec) -> [u8;32] { self.sto.insert(leaf_hash, node_type, index_length, leaf_value); let mut curr_node = leaf_hash; for i in 0..siblings.len() { - if path[i as usize] { + if !path[i as usize] { let node = node::TreeNode { child_l: curr_node, child_r: siblings[siblings.len()-1-i], }; - self.sto.insert(node.ht(), TYPENODENORMAL, 0, &mut node.bytes()); + self.sto.insert(node.ht(), TYPENODENORMAL, 0, node.bytes()); curr_node = node.ht(); } else { let node = node::TreeNode { child_l: siblings[siblings.len()-1-i], child_r: curr_node, }; - self.sto.insert(node.ht(), TYPENODENORMAL, 0, &mut node.bytes()); + self.sto.insert(node.ht(), TYPENODENORMAL, 0, node.bytes()); curr_node = node.ht(); } } @@ -226,165 +230,161 @@ impl MerkleTree { } else { node_hash = node.child_r; } + } + let (_t, _il, node_bytes) = self.sto.get(&node_hash); + node_bytes } - let (_t, _il, node_bytes) = self.sto.get(&node_hash); - node_bytes - } - - #[allow(dead_code)] - pub fn generate_proof(&self, hi: [u8;32]) -> Vec { - let mut mp: Vec = Vec::new(); - let mut empties: [u8;32] = [0;32]; - let path = utils::get_path(self.num_levels, hi); - - let mut siblings: Vec<[u8;32]> = Vec::new(); - let mut node_hash = self.root; - - for i in 0..self.num_levels { - let (t, il, node_bytes) = self.sto.get(&node_hash); - if t == TYPENODEFINAL { - let real_value_in_pos = self.get_value_in_pos(hi); - if real_value_in_pos == EMPTYNODEVALUE { - let leaf_hi = utils::hash_vec(node_bytes.to_vec().split_at(il as usize).0.to_vec()); - let path_child = utils::get_path(self.num_levels, leaf_hi); - let pos_diff = utils::compare_paths(&path_child, &path); - if pos_diff == self.num_levels { // TODO use a match here, and instead of 999 return something better - return mp; - } - if pos_diff != self.num_levels-1-i { - let sibling = utils::calc_hash_from_leaf_and_level(pos_diff, &path_child, utils::hash_vec(node_bytes.to_vec())); - let mut new_siblings: Vec<[u8;32]> = Vec::new(); - new_siblings.push(sibling); - new_siblings.append(&mut siblings); - siblings = new_siblings; - // set empties bit - let bit_pos = self.num_levels-2-pos_diff; - empties[(empties.len() as isize + (bit_pos as isize/8-1) as isize) as usize] |= 1 << (bit_pos%8); + #[allow(dead_code)] + pub fn generate_proof(&self, hi: [u8;32]) -> Vec { + let mut mp: Vec = Vec::new(); + + let mut empties: [u8;32] = [0;32]; + let path = utils::get_path(self.num_levels, hi); + + let mut siblings: Vec<[u8;32]> = Vec::new(); + let mut node_hash = self.root; + + for i in 0..self.num_levels { + let (t, il, node_bytes) = self.sto.get(&node_hash); + if t == TYPENODEFINAL { + let real_value_in_pos = self.get_value_in_pos(hi); + if real_value_in_pos == EMPTYNODEVALUE { + let leaf_hi = utils::hash_vec(node_bytes.to_vec().split_at(il as usize).0.to_vec()); + let path_child = utils::get_path(self.num_levels, leaf_hi); + let pos_diff = utils::compare_paths(&path_child, &path); + if pos_diff == self.num_levels { // TODO use a match here, and instead of 999 return something better + return mp; + } + if pos_diff != self.num_levels-1-i { + let sibling = utils::calc_hash_from_leaf_and_level(pos_diff, &path_child, utils::hash_vec(node_bytes.to_vec())); + let mut new_siblings: Vec<[u8;32]> = Vec::new(); + new_siblings.push(sibling); + new_siblings.extend(siblings); + siblings = new_siblings; + // set empties bit + let bit_pos = self.num_levels-2-pos_diff; + empties[(empties.len() as isize + (bit_pos as isize/8-1) as isize) as usize] |= 1 << (bit_pos%8); + } } + break + } + let node = node::parse_node_bytes(node_bytes); + let sibling: [u8;32]; + if !path[self.num_levels as usize -i as usize -2] { + node_hash = node.child_l; + sibling = node.child_r; + } else { + sibling = node.child_l; + node_hash = node.child_r; + } + if sibling != EMPTYNODEVALUE { + // set empties bit + empties[(empties.len() as isize + (i as isize/8-1) as isize) as usize] |= 1 << (i%8); + let mut new_siblings: Vec<[u8;32]> = Vec::new(); + new_siblings.push(sibling); + new_siblings.extend(siblings); + siblings = new_siblings; } - break - } - let node = node::parse_node_bytes(node_bytes); - let sibling: [u8;32]; - if !path[self.num_levels as usize -i as usize -2] { - node_hash = node.child_l; - sibling = node.child_r; - } else { - sibling = node.child_l; - node_hash = node.child_r; } - if sibling != EMPTYNODEVALUE { - // set empties bit - empties[(empties.len() as isize + (i as isize/8-1) as isize) as usize] |= 1 << (i%8); - let mut new_siblings: Vec<[u8;32]> = Vec::new(); - new_siblings.push(sibling); - new_siblings.append(&mut siblings); - siblings = new_siblings; + mp.append(&mut empties[..].to_vec()); + for s in siblings { + mp.append(&mut s.to_vec()); } + mp } - mp.append(&mut empties[..].to_vec()); - for s in siblings { - mp.append(&mut s.to_vec()); - } - mp - } - #[allow(dead_code)] - pub fn print_level(&self, parent: [u8;32], mut lvl: u32, max_level: u32) { - use rustc_hex::ToHex; - - let mut line: String = "".to_string(); - for _ in 0..lvl { - line += &" ".to_string(); - } - line += &("lvl ".to_string() + &lvl.to_string()); - line += &(" - '".to_string() + &parent.to_hex() + &"' = ".to_string()); - let (t, _, node_bytes) = self.sto.get(&parent); - let mut node = node::TreeNode { - child_l: EMPTYNODEVALUE, - child_r: EMPTYNODEVALUE, - }; - if t==TYPENODENORMAL { - node = node::parse_node_bytes(node_bytes); - line += &("'".to_string() + &node.child_l.to_hex() + &"' - '".to_string() + &node.child_r.to_hex() + &"'".to_string()); - } else if t == TYPENODEVALUE { - // - } else if t == TYPENODEFINAL { - let hash_node_bytes = utils::hash_vec(node_bytes); - line += &("[final] final tree node: ".to_string() + &hash_node_bytes.to_hex()+ &"\n".to_string()); - let (_, _, leaf_node_bytes) = self.sto.get(&hash_node_bytes); + #[allow(dead_code)] + pub fn print_level(&self, parent: [u8;32], mut lvl: u32, max_level: u32) { + let mut line: String = "".to_string(); for _ in 0..lvl { - line += " "; + line += &format!(" "); + } + line += &format!("lvl {}", lvl); + line += &format!(" - '{}' = ", parent.to_hex()); + let (t, _, node_bytes) = self.sto.get(&parent); + let mut node = node::TreeNode { + child_l: EMPTYNODEVALUE, + child_r: EMPTYNODEVALUE, + }; + if t==TYPENODENORMAL { + node = node::parse_node_bytes(node_bytes); + line += &format!("'{}' - '{}'", node.child_l.to_hex(), node.child_r.to_hex()); + } else if t == TYPENODEVALUE { + // + } else if t == TYPENODEFINAL { + let hash_node_bytes = utils::hash_vec(node_bytes); + line += &format!("[final] final tree node: {} \n", hash_node_bytes.to_hex()); + let (_, _, leaf_node_bytes) = self.sto.get(&hash_node_bytes); + for _ in 0..lvl { + line += " "; + } + let leaf_node_string = String::from_utf8_lossy(&leaf_node_bytes); + line += &format!("leaf value: {}", leaf_node_string); + } else { + line += "[EMPTY Branch]" + } + println!("{}", line); + lvl += 1; + if node.child_r.len()>0 && lvl0 && lvl, hi: [u8;32], ht: [u8;32], num_levels: u32) -> bool { - let empties: Vec; - empties = mp.split_at(32).0.to_vec(); - - let mut siblings: Vec<[u8;32]> = Vec::new(); - for i in (empties.len()..mp.len()).step_by(EMPTYNODEVALUE.len()) { - let mut sibling: [u8;32] = [0;32]; - sibling.copy_from_slice(&mp[i..i+EMPTYNODEVALUE.len()]); - siblings.push(sibling); - } + pub fn verify_proof(root: [u8;32], mp: Vec, hi: [u8;32], ht: [u8;32], num_levels: u32) -> bool { + let empties: Vec; + empties = mp.split_at(32).0.to_vec(); - let path = utils::get_path(num_levels, hi); - let mut node_hash = ht; - let mut sibling_used_pos = 0; - - for i in (0..=num_levels-2).rev() { - let sibling: [u8;32]; - if (empties[empties.len()-i as usize/8-1] & (1 << (i%8))) > 0 { - sibling = siblings[sibling_used_pos]; - sibling_used_pos += 1; - } else { - sibling = EMPTYNODEVALUE; + let mut siblings: Vec<[u8;32]> = Vec::new(); + for i in (empties.len()..mp.len()).step_by(EMPTYNODEVALUE.len()) { + let mut sibling: [u8;32] = [0;32]; + sibling.copy_from_slice(&mp[i..i+EMPTYNODEVALUE.len()]); + siblings.push(sibling); } - let n: node::TreeNode; - if path[num_levels as usize - i as usize-2] { - n = node::TreeNode { - child_l: sibling, - child_r: node_hash, - }} else { - n = node::TreeNode { - child_l: node_hash, - child_r: sibling, - }} - if node_hash == EMPTYNODEVALUE && sibling == EMPTYNODEVALUE { - node_hash = EMPTYNODEVALUE; - } else { - node_hash = n.ht(); + let path = utils::get_path(num_levels, hi); + let mut node_hash = ht; + let mut sibling_used_pos = 0; + + for i in (0..=num_levels-2).rev() { + let sibling: [u8;32]; + if (empties[empties.len()-i as usize/8-1] & (1 << (i%8))) > 0 { + sibling = siblings[sibling_used_pos]; + sibling_used_pos += 1; + } else { + sibling = EMPTYNODEVALUE; + } + + let n: node::TreeNode; + if path[num_levels as usize - i as usize-2] { + n = node::TreeNode { + child_l: sibling, + child_r: node_hash, + }} else { + n = node::TreeNode { + child_l: node_hash, + child_r: sibling, + }} + if node_hash == EMPTYNODEVALUE && sibling == EMPTYNODEVALUE { + node_hash = EMPTYNODEVALUE; + } else { + node_hash = n.ht(); + } } + if node_hash==root { + return true; + } + false } - if node_hash==root { - return true; - } - false -} #[cfg(test)] @@ -433,83 +433,86 @@ pub fn verify_proof(root: [u8;32], mp: Vec, hi: [u8;32], ht: [u8;32], num_le assert_eq!(*val.bytes(), b); assert_eq!("a0e72cc948119fcb71b413cf5ada12b2b825d5133299b20a6d9325ffc3e2fbf1", mt.root.to_hex()); } + #[test] fn test_add_2() { - let mut mt: MerkleTree = new(140); - let val = TestValue { - bytes: "this is a test leaf".as_bytes().to_vec(), - index_length: 15, - }; - assert_eq!("0000000000000000000000000000000000000000000000000000000000000000", mt.root.to_hex()); - mt.add(&val); - let (_t, _il, b) = mt.sto.get(&val.ht()); - assert_eq!(*val.bytes(), b); - assert_eq!("b4fdf8a653198f0e179ccb3af7e4fc09d76247f479d6cfc95cd92d6fda589f27", mt.root.to_hex()); - let val2 = TestValue { - bytes: "this is a second test leaf".as_bytes().to_vec(), - index_length: 15, - }; - mt.add(&val2); - let (_t, _il, b) = mt.sto.get(&val2.ht()); - assert_eq!(*val2.bytes(), b); - assert_eq!("8ac95e9c8a6fbd40bb21de7895ee35f9c8f30ca029dbb0972c02344f49462e82", mt.root.to_hex()); - mt.print_full_tree(); + let mut mt: MerkleTree = new(140); + let val = TestValue { + bytes: "this is a test leaf".as_bytes().to_vec(), + index_length: 15, + }; + assert_eq!("0000000000000000000000000000000000000000000000000000000000000000", mt.root.to_hex()); + mt.add(&val); + let (_t, _il, b) = mt.sto.get(&val.ht()); + assert_eq!(*val.bytes(), b); + assert_eq!("b4fdf8a653198f0e179ccb3af7e4fc09d76247f479d6cfc95cd92d6fda589f27", mt.root.to_hex()); + let val2 = TestValue { + bytes: "this is a second test leaf".as_bytes().to_vec(), + index_length: 15, + }; + mt.add(&val2); + let (_t, _il, b) = mt.sto.get(&val2.ht()); + assert_eq!(*val2.bytes(), b); + assert_eq!("8ac95e9c8a6fbd40bb21de7895ee35f9c8f30ca029dbb0972c02344f49462e82", mt.root.to_hex()); } + #[test] fn test_generate_proof_and_verify_proof() { - let mut mt: MerkleTree = new(140); - let val = TestValue { - bytes: "this is a test leaf".as_bytes().to_vec(), - index_length: 15, - }; - assert_eq!("0000000000000000000000000000000000000000000000000000000000000000", mt.root.to_hex()); - mt.add(&val); - let (_t, _il, b) = mt.sto.get(&val.ht()); - assert_eq!(*val.bytes(), b); - assert_eq!("b4fdf8a653198f0e179ccb3af7e4fc09d76247f479d6cfc95cd92d6fda589f27", mt.root.to_hex()); - let val2 = TestValue { - bytes: "this is a second test leaf".as_bytes().to_vec(), - index_length: 15, - }; - mt.add(&val2); - let (_t, _il, b) = mt.sto.get(&val2.ht()); - assert_eq!(*val2.bytes(), b); - assert_eq!("8ac95e9c8a6fbd40bb21de7895ee35f9c8f30ca029dbb0972c02344f49462e82", mt.root.to_hex()); - - let mp = mt.generate_proof(val2.hi()); - assert_eq!("0000000000000000000000000000000000000000000000000000000000000001fd8e1a60cdb23c0c7b2cf8462c99fafd905054dccb0ed75e7c8a7d6806749b6b", mp.to_hex()); - - // verify - let v = verify_proof(mt.root, mp, val2.hi(), val2.ht(), mt.num_levels); - assert_eq!(true, v); + let mut mt: MerkleTree = new(140); + let val = TestValue { + bytes: "this is a test leaf".as_bytes().to_vec(), + index_length: 15, + }; + assert_eq!("0000000000000000000000000000000000000000000000000000000000000000", mt.root.to_hex()); + mt.add(&val); + let (_t, _il, b) = mt.sto.get(&val.ht()); + assert_eq!(*val.bytes(), b); + assert_eq!("b4fdf8a653198f0e179ccb3af7e4fc09d76247f479d6cfc95cd92d6fda589f27", mt.root.to_hex()); + let val2 = TestValue { + bytes: "this is a second test leaf".as_bytes().to_vec(), + index_length: 15, + }; + mt.add(&val2); + let (_t, _il, b) = mt.sto.get(&val2.ht()); + assert_eq!(*val2.bytes(), b); + assert_eq!("8ac95e9c8a6fbd40bb21de7895ee35f9c8f30ca029dbb0972c02344f49462e82", mt.root.to_hex()); + + let mp = mt.generate_proof(val2.hi()); + assert_eq!("0000000000000000000000000000000000000000000000000000000000000001fd8e1a60cdb23c0c7b2cf8462c99fafd905054dccb0ed75e7c8a7d6806749b6b", mp.to_hex()); + + // verify + let v = verify_proof(mt.root, mp, val2.hi(), val2.ht(), mt.num_levels); + assert_eq!(true, v); } + #[test] fn test_generate_proof_empty_leaf_and_verify_proof() { - let mut mt: MerkleTree = new(140); - let val = TestValue { - bytes: "this is a test leaf".as_bytes().to_vec(), - index_length: 15, - }; - mt.add(&val); - let val2 = TestValue { - bytes: "this is a second test leaf".as_bytes().to_vec(), - index_length: 15, - }; - mt.add(&val2); - assert_eq!("8ac95e9c8a6fbd40bb21de7895ee35f9c8f30ca029dbb0972c02344f49462e82", mt.root.to_hex()); + let mut mt: MerkleTree = new(140); + let val = TestValue { + bytes: "this is a test leaf".as_bytes().to_vec(), + index_length: 15, + }; + mt.add(&val); + let val2 = TestValue { + bytes: "this is a second test leaf".as_bytes().to_vec(), + index_length: 15, + }; + mt.add(&val2); + assert_eq!("8ac95e9c8a6fbd40bb21de7895ee35f9c8f30ca029dbb0972c02344f49462e82", mt.root.to_hex()); // proof of empty leaf - let val3 = TestValue { - bytes: "this is a third test leaf".as_bytes().to_vec(), - index_length: 15, - }; - let mp = mt.generate_proof(val3.hi()); - assert_eq!("000000000000000000000000000000000000000000000000000000000000000389741fa23da77c259781ad8f4331a5a7d793eef1db7e5200ddfc8e5f5ca7ce2bfd8e1a60cdb23c0c7b2cf8462c99fafd905054dccb0ed75e7c8a7d6806749b6b", mp.to_hex()); - - // verify that is a proof of an empty leaf (EMPTYNODEVALUE) - let v = verify_proof(mt.root, mp, val3.hi(), EMPTYNODEVALUE, mt.num_levels); - assert_eq!(true, v); + let val3 = TestValue { + bytes: "this is a third test leaf".as_bytes().to_vec(), + index_length: 15, + }; + let mp = mt.generate_proof(val3.hi()); + assert_eq!("000000000000000000000000000000000000000000000000000000000000000389741fa23da77c259781ad8f4331a5a7d793eef1db7e5200ddfc8e5f5ca7ce2bfd8e1a60cdb23c0c7b2cf8462c99fafd905054dccb0ed75e7c8a7d6806749b6b", mp.to_hex()); + + // verify that is a proof of an empty leaf (EMPTYNODEVALUE) + let v = verify_proof(mt.root, mp, val3.hi(), EMPTYNODEVALUE, mt.num_levels); + assert_eq!(true, v); } + #[test] fn test_harcoded_proofs_of_existing_leaf() { // check proof of value in leaf @@ -520,9 +523,10 @@ pub fn verify_proof(root: [u8;32], mp: Vec, hi: [u8;32], ht: [u8;32], num_le hi.copy_from_slice(&hex::decode("786677808ba77bdd9090a969f1ef2cbd1ac5aecd9e654f340500159219106878").unwrap()); let mut ht: [u8;32] = [0;32]; ht.copy_from_slice(&hex::decode("786677808ba77bdd9090a969f1ef2cbd1ac5aecd9e654f340500159219106878").unwrap()); - let v = verify_proof(root, mp, hi, ht, 140); - assert_eq!(true, v); + let v = verify_proof(root, mp, hi, ht, 140); + assert_eq!(true, v); } + #[test] fn test_harcoded_proofs_of_empty_leaf() { // check proof of value in leaf @@ -531,7 +535,41 @@ pub fn verify_proof(root: [u8;32], mp: Vec, hi: [u8;32], ht: [u8;32], num_le let mp = hex::decode("0000000000000000000000000000000000000000000000000000000000000004bf8e980d2ed328ae97f65c30c25520aeb53ff837579e392ea1464934c7c1feb9").unwrap(); let mut hi: [u8;32] = [0;32]; hi.copy_from_slice(&hex::decode("a69792a4cff51f40b7a1f7ae596c6ded4aba241646a47538898f17f2a8dff647").unwrap()); - let v = verify_proof(root, mp, hi, EMPTYNODEVALUE, 140); - assert_eq!(true, v); + let v = verify_proof(root, mp, hi, EMPTYNODEVALUE, 140); + assert_eq!(true, v); + } + + #[test] + fn test_add_leafs_different_order() { + let mut mt1: MerkleTree = new(140); + mt1.add(&TestValue {bytes: "0 this is a test leaf".as_bytes().to_vec(), index_length: 15,}); + mt1.add(&TestValue {bytes: "1 this is a test leaf".as_bytes().to_vec(), index_length: 15,}); + mt1.add(&TestValue {bytes: "2 this is a test leaf".as_bytes().to_vec(), index_length: 15,}); + mt1.add(&TestValue {bytes: "3 this is a test leaf".as_bytes().to_vec(), index_length: 15,}); + mt1.add(&TestValue {bytes: "4 this is a test leaf".as_bytes().to_vec(), index_length: 15,}); + mt1.add(&TestValue {bytes: "5 this is a test leaf".as_bytes().to_vec(), index_length: 15,}); + mt1.print_full_tree(); + + + let mut mt2: MerkleTree = new(140); + mt2.add(&TestValue {bytes: "2 this is a test leaf".as_bytes().to_vec(), index_length: 15,}); + mt2.add(&TestValue {bytes: "1 this is a test leaf".as_bytes().to_vec(), index_length: 15,}); + mt2.add(&TestValue {bytes: "0 this is a test leaf".as_bytes().to_vec(), index_length: 15,}); + mt2.add(&TestValue {bytes: "5 this is a test leaf".as_bytes().to_vec(), index_length: 15,}); + mt2.add(&TestValue {bytes: "3 this is a test leaf".as_bytes().to_vec(), index_length: 15,}); + mt2.add(&TestValue {bytes: "4 this is a test leaf".as_bytes().to_vec(), index_length: 15,}); + mt2.print_full_tree(); + + assert_eq!(mt1.root, mt2.root); + assert_eq!(mt1.root.to_hex(), "264397f84da141b3134dcde1d7540d27a2bf0d787bbe8365d9ad5c9c18d3c621"); + } + + #[test] + fn test_add_1000_leafs() { + let mut mt: MerkleTree = new(140); + for i in 0..1000 { + mt.add(&TestValue {bytes: (i.to_string()+" this is a test leaf").as_bytes().to_vec(), index_length: 15,}); + } + assert_eq!(mt.root.to_hex(), "6e2da580b2920cd78ed8d4e4bf41e209dfc99ef28bc19560042f0ac803e0d6f7"); } } diff --git a/src/utils.rs b/src/utils.rs index a335511..9d31bf3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -2,7 +2,6 @@ use node; use tiny_keccak::Keccak; pub fn hash_vec(b: Vec) -> [u8; 32] { - // let mut sha3 = Keccak::new_sha3_256(); let mut sha3 = Keccak::new_keccak256(); sha3.update(&b); let mut res: [u8; 32] = [0; 32]; @@ -13,7 +12,7 @@ pub fn hash_vec(b: Vec) -> [u8; 32] { #[allow(dead_code)] pub fn get_path(num_levels: u32, hi: [u8;32]) -> Vec { let mut path = Vec::new(); - for i in (0..num_levels as usize-1).rev() { + for i in (0..=num_levels as usize-2).rev() { path.push((hi[hi.len()-i/8-1] & (1 << (i%8))) > 0); } path @@ -42,9 +41,9 @@ pub fn calc_hash_from_leaf_and_level(until_level: u32, path: &[bool], leaf_hash: pub fn cut_path(path: &[bool], i: usize) -> Vec { let mut path_res: Vec = Vec::new(); - for (j, path_elem) in path.iter().enumerate() { - if j >= i { - path_res.push(*path_elem); + for j in 0..path.len() { + if j>=i { + path_res.push(path[j]); } } path_res @@ -61,7 +60,7 @@ pub fn compare_paths(a: &[bool], b: &[bool]) -> u32 { pub fn get_empties_between_i_and_pos(i: u32, pos: u32) -> Vec<[u8;32]> { let mut sibl: Vec<[u8;32]> = Vec::new(); - for _ in (pos..i).rev() { + for _ in (pos..=i).rev() { sibl.push(::EMPTYNODEVALUE); } sibl