mirror of
https://github.com/arnaucube/merkletree-rs.git
synced 2026-02-28 05:36:47 +01:00
update & some fixes & travis
This commit is contained in:
9
.travis.yml
Normal file
9
.travis.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
language: rust
|
||||
rust:
|
||||
- stable
|
||||
|
||||
cache:
|
||||
- cargo
|
||||
|
||||
script:
|
||||
- RUST_BACKTRACE=1 cargo test --all
|
||||
@@ -1,8 +1,10 @@
|
||||
# merkletree-rs
|
||||
# merkletree-rs [](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:
|
||||
|
||||
508
src/lib.rs
508
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<u8>>,
|
||||
}
|
||||
impl Db {
|
||||
pub fn insert(&mut self, k: [u8; 32], t: u8, il: u32, b: &mut Vec<u8>) {
|
||||
pub fn insert(&mut self, k: [u8; 32], t: u8, il: u32, b: Vec<u8>) {
|
||||
let mut v: Vec<u8>;
|
||||
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<u8>) {
|
||||
@@ -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<bool>, siblings: Vec<[u8;32]>, leaf_hash: [u8;32], node_type: u8, index_length: u32, leaf_value: &mut Vec<u8>) -> [u8;32] {
|
||||
pub fn replace_leaf(&mut self, path: Vec<bool>, siblings: &Vec<[u8;32]>, leaf_hash: [u8;32], node_type: u8, index_length: u32, leaf_value: Vec<u8>) -> [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
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn generate_proof(&self, hi: [u8;32]) -> Vec<u8> {
|
||||
let mut mp: Vec<u8> = 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;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
let mut line: String = "".to_string();
|
||||
for _ in 0..lvl {
|
||||
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 && lvl<max_level && t != TYPENODEEMPTY && t != TYPENODEFINAL {
|
||||
self.print_level(node.child_l, lvl, max_level);
|
||||
self.print_level(node.child_r, lvl, max_level);
|
||||
}
|
||||
}
|
||||
pub fn print_full_tree(&self) {
|
||||
self.print_level(self.root, 0, self.num_levels - 1);
|
||||
println!("root {:?}", self.root.to_hex());
|
||||
}
|
||||
pub fn print_levels_tree(&self, max_level: u32) {
|
||||
self.print_level(self.root, 0, self.num_levels - 1 - max_level);
|
||||
println!("root {:?}", self.root.to_hex());
|
||||
}
|
||||
let (_t, _il, node_bytes) = self.sto.get(&node_hash);
|
||||
node_bytes
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn generate_proof(&self, hi: [u8;32]) -> Vec<u8> {
|
||||
let mut mp: Vec<u8> = Vec::new();
|
||||
|
||||
let mut empties: [u8;32] = [0;32];
|
||||
let path = utils::get_path(self.num_levels, hi);
|
||||
#[allow(dead_code)]
|
||||
pub fn verify_proof(root: [u8;32], mp: Vec<u8>, hi: [u8;32], ht: [u8;32], num_levels: u32) -> bool {
|
||||
let empties: Vec<u8>;
|
||||
empties = mp.split_at(32).0.to_vec();
|
||||
|
||||
let mut siblings: Vec<[u8;32]> = Vec::new();
|
||||
let mut node_hash = self.root;
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
let node = node::parse_node_bytes(node_bytes);
|
||||
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 !path[self.num_levels as usize -i as usize -2] {
|
||||
node_hash = node.child_l;
|
||||
sibling = node.child_r;
|
||||
if (empties[empties.len()-i as usize/8-1] & (1 << (i%8))) > 0 {
|
||||
sibling = siblings[sibling_used_pos];
|
||||
sibling_used_pos += 1;
|
||||
} else {
|
||||
sibling = node.child_l;
|
||||
node_hash = node.child_r;
|
||||
sibling = EMPTYNODEVALUE;
|
||||
}
|
||||
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;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
mp.append(&mut empties[..].to_vec());
|
||||
for s in siblings {
|
||||
mp.append(&mut s.to_vec());
|
||||
if node_hash==root {
|
||||
return true;
|
||||
}
|
||||
mp
|
||||
false
|
||||
}
|
||||
#[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);
|
||||
for _ in 0..lvl {
|
||||
line += " ";
|
||||
}
|
||||
let leaf_node_string = String::from_utf8_lossy(&leaf_node_bytes);
|
||||
line += &("leaf value: ".to_string() + &leaf_node_string);
|
||||
} else {
|
||||
line += &"[EMPTY Branch]".to_string()
|
||||
}
|
||||
println!("{:?}", line);
|
||||
lvl += 1;
|
||||
if node.child_r.len()>0 && lvl<max_level && t != TYPENODEEMPTY && t != TYPENODEFINAL {
|
||||
self.print_level(node.child_l, lvl, max_level);
|
||||
self.print_level(node.child_r, lvl, max_level);
|
||||
}
|
||||
}
|
||||
pub fn print_full_tree(&self) {
|
||||
use rustc_hex::ToHex;
|
||||
self.print_level(self.root, 0, self.num_levels - 1);
|
||||
println!("root {:?}", self.root.to_hex());
|
||||
}
|
||||
pub fn print_levels_tree(&self, max_level: u32) {
|
||||
use rustc_hex::ToHex;
|
||||
self.print_level(self.root, 0, self.num_levels - 1 - max_level);
|
||||
println!("root {:?}", self.root.to_hex());
|
||||
}
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
pub fn verify_proof(root: [u8;32], mp: Vec<u8>, hi: [u8;32], ht: [u8;32], num_levels: u32) -> bool {
|
||||
let empties: Vec<u8>;
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -433,83 +433,86 @@ pub fn verify_proof(root: [u8;32], mp: Vec<u8>, 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 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());
|
||||
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);
|
||||
// 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());
|
||||
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);
|
||||
// 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<u8>, 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<u8>, 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");
|
||||
}
|
||||
}
|
||||
|
||||
11
src/utils.rs
11
src/utils.rs
@@ -2,7 +2,6 @@ use node;
|
||||
use tiny_keccak::Keccak;
|
||||
|
||||
pub fn hash_vec(b: Vec<u8>) -> [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>) -> [u8; 32] {
|
||||
#[allow(dead_code)]
|
||||
pub fn get_path(num_levels: u32, hi: [u8;32]) -> Vec<bool> {
|
||||
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<bool> {
|
||||
let mut path_res: Vec<bool> = 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
|
||||
|
||||
Reference in New Issue
Block a user