update & some fixes & travis

This commit is contained in:
arnaucube
2019-07-07 16:54:27 +02:00
parent 073d9fe6c9
commit 0e84b1172e
4 changed files with 291 additions and 243 deletions

9
.travis.yml Normal file
View File

@@ -0,0 +1,9 @@
language: rust
rust:
- stable
cache:
- cargo
script:
- RUST_BACKTRACE=1 cargo test --all

View File

@@ -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. 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. 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 ## Usage
Create new tree: Create new tree:

View File

@@ -9,6 +9,8 @@ extern crate rustc_hex;
extern crate hex; extern crate hex;
use rustc_hex::ToHex;
mod utils; mod utils;
mod node; mod node;
@@ -48,12 +50,12 @@ pub struct Db {
storage: HashMap<[u8;32], Vec<u8>>, storage: HashMap<[u8;32], Vec<u8>>,
} }
impl Db { 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>; let mut v: Vec<u8>;
v = [t].to_vec(); v = [t].to_vec();
let il_bytes = il.to_le_bytes(); let il_bytes = il.to_le_bytes();
v.append(&mut il_bytes.to_vec()); // il_bytes are [u8;4] (4 bytes) v.extend(il_bytes.to_vec()); // il_bytes are [u8;4] (4 bytes)
v.append(b); v.extend(&b);
self.storage.insert(k, v); self.storage.insert(k, v);
} }
pub fn get(&self, k: &[u8;32]) -> (u8, u32, Vec<u8>) { pub fn get(&self, k: &[u8;32]) -> (u8, u32, Vec<u8>) {
@@ -102,9 +104,9 @@ impl MerkleTree {
#![allow(unused_variables)] #![allow(unused_variables)]
#[allow(dead_code)] #[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 // 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 index = v.index_length() as usize;
let hi = v.hi(); let hi = v.hi();
@@ -123,13 +125,14 @@ impl MerkleTree {
let path_child = utils::get_path(self.num_levels, hi_child); let path_child = utils::get_path(self.num_levels, hi_child);
let pos_diff = utils::compare_paths(&path_child, &path); 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 if pos_diff == 999 { // TODO use a match here, and instead of 999 return something better
println!("node already exists");
println!("compare paths err"); println!("compare paths err");
return; return;
} }
let final_node_1_hash = utils::calc_hash_from_leaf_and_level(pos_diff, &path_child, utils::hash_vec(node_bytes.to_vec())); 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()); 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 // parent node
let parent_node: node::TreeNode; let parent_node: node::TreeNode;
@@ -147,15 +150,16 @@ impl MerkleTree {
siblings.push(*empty); siblings.push(*empty);
} }
let path_from_pos_diff = utils::cut_path(&path, (pos_diff +1) as usize); 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());
self.root = self.replace_leaf(path_from_pos_diff, &siblings, parent_node.ht(), TYPENODENORMAL, 0, parent_node.bytes().to_vec());
return; return;
} }
let node = node::parse_node_bytes(node_bytes); let node = node::parse_node_bytes(node_bytes);
let sibling: [u8;32]; let sibling: [u8;32];
if path[i as usize] { if !path[i as usize] {
node_hash = node.child_l; node_hash = node.child_l;
sibling = node.child_r; sibling = node.child_r;
} else { } else {
@@ -166,38 +170,38 @@ impl MerkleTree {
if node_hash == EMPTYNODEVALUE { if node_hash == EMPTYNODEVALUE {
if i==self.num_levels-2 && siblings[siblings.len()-1]==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()); 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; self.root = final_node_hash;
return; return;
} }
let final_node_hash = utils::calc_hash_from_leaf_and_level(i, &path, v.ht()); 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); 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; 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)] #[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); self.sto.insert(leaf_hash, node_type, index_length, leaf_value);
let mut curr_node = leaf_hash; let mut curr_node = leaf_hash;
for i in 0..siblings.len() { for i in 0..siblings.len() {
if path[i as usize] { if !path[i as usize] {
let node = node::TreeNode { let node = node::TreeNode {
child_l: curr_node, child_l: curr_node,
child_r: siblings[siblings.len()-1-i], 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(); curr_node = node.ht();
} else { } else {
let node = node::TreeNode { let node = node::TreeNode {
child_l: siblings[siblings.len()-1-i], child_l: siblings[siblings.len()-1-i],
child_r: curr_node, 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(); curr_node = node.ht();
} }
} }
@@ -256,7 +260,7 @@ impl MerkleTree {
let sibling = utils::calc_hash_from_leaf_and_level(pos_diff, &path_child, utils::hash_vec(node_bytes.to_vec())); 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(); let mut new_siblings: Vec<[u8;32]> = Vec::new();
new_siblings.push(sibling); new_siblings.push(sibling);
new_siblings.append(&mut siblings); new_siblings.extend(siblings);
siblings = new_siblings; siblings = new_siblings;
// set empties bit // set empties bit
let bit_pos = self.num_levels-2-pos_diff; let bit_pos = self.num_levels-2-pos_diff;
@@ -279,7 +283,7 @@ impl MerkleTree {
empties[(empties.len() as isize + (i as isize/8-1) as isize) as usize] |= 1 << (i%8); 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(); let mut new_siblings: Vec<[u8;32]> = Vec::new();
new_siblings.push(sibling); new_siblings.push(sibling);
new_siblings.append(&mut siblings); new_siblings.extend(siblings);
siblings = new_siblings; siblings = new_siblings;
} }
} }
@@ -291,14 +295,12 @@ impl MerkleTree {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub fn print_level(&self, parent: [u8;32], mut lvl: u32, max_level: u32) { pub fn print_level(&self, parent: [u8;32], mut lvl: u32, max_level: u32) {
use rustc_hex::ToHex;
let mut line: String = "".to_string(); let mut line: String = "".to_string();
for _ in 0..lvl { for _ in 0..lvl {
line += &" ".to_string(); line += &format!(" ");
} }
line += &("lvl ".to_string() + &lvl.to_string()); line += &format!("lvl {}", lvl);
line += &(" - '".to_string() + &parent.to_hex() + &"' = ".to_string()); line += &format!(" - '{}' = ", parent.to_hex());
let (t, _, node_bytes) = self.sto.get(&parent); let (t, _, node_bytes) = self.sto.get(&parent);
let mut node = node::TreeNode { let mut node = node::TreeNode {
child_l: EMPTYNODEVALUE, child_l: EMPTYNODEVALUE,
@@ -306,22 +308,22 @@ impl MerkleTree {
}; };
if t==TYPENODENORMAL { if t==TYPENODENORMAL {
node = node::parse_node_bytes(node_bytes); node = node::parse_node_bytes(node_bytes);
line += &("'".to_string() + &node.child_l.to_hex() + &"' - '".to_string() + &node.child_r.to_hex() + &"'".to_string()); line += &format!("'{}' - '{}'", node.child_l.to_hex(), node.child_r.to_hex());
} else if t == TYPENODEVALUE { } else if t == TYPENODEVALUE {
// //
} else if t == TYPENODEFINAL { } else if t == TYPENODEFINAL {
let hash_node_bytes = utils::hash_vec(node_bytes); let hash_node_bytes = utils::hash_vec(node_bytes);
line += &("[final] final tree node: ".to_string() + &hash_node_bytes.to_hex()+ &"\n".to_string()); line += &format!("[final] final tree node: {} \n", hash_node_bytes.to_hex());
let (_, _, leaf_node_bytes) = self.sto.get(&hash_node_bytes); let (_, _, leaf_node_bytes) = self.sto.get(&hash_node_bytes);
for _ in 0..lvl { for _ in 0..lvl {
line += " "; line += " ";
} }
let leaf_node_string = String::from_utf8_lossy(&leaf_node_bytes); let leaf_node_string = String::from_utf8_lossy(&leaf_node_bytes);
line += &("leaf value: ".to_string() + &leaf_node_string); line += &format!("leaf value: {}", leaf_node_string);
} else { } else {
line += &"[EMPTY Branch]".to_string() line += "[EMPTY Branch]"
} }
println!("{:?}", line); println!("{}", line);
lvl += 1; lvl += 1;
if node.child_r.len()>0 && lvl<max_level && t != TYPENODEEMPTY && t != TYPENODEFINAL { 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_l, lvl, max_level);
@@ -329,18 +331,16 @@ impl MerkleTree {
} }
} }
pub fn print_full_tree(&self) { pub fn print_full_tree(&self) {
use rustc_hex::ToHex;
self.print_level(self.root, 0, self.num_levels - 1); self.print_level(self.root, 0, self.num_levels - 1);
println!("root {:?}", self.root.to_hex()); println!("root {:?}", self.root.to_hex());
} }
pub fn print_levels_tree(&self, max_level: u32) { 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); self.print_level(self.root, 0, self.num_levels - 1 - max_level);
println!("root {:?}", self.root.to_hex()); println!("root {:?}", self.root.to_hex());
} }
} }
#[allow(dead_code)] #[allow(dead_code)]
pub fn verify_proof(root: [u8;32], mp: Vec<u8>, hi: [u8;32], ht: [u8;32], num_levels: u32) -> bool { pub fn verify_proof(root: [u8;32], mp: Vec<u8>, hi: [u8;32], ht: [u8;32], num_levels: u32) -> bool {
let empties: Vec<u8>; let empties: Vec<u8>;
empties = mp.split_at(32).0.to_vec(); empties = mp.split_at(32).0.to_vec();
@@ -384,7 +384,7 @@ pub fn verify_proof(root: [u8;32], mp: Vec<u8>, hi: [u8;32], ht: [u8;32], num_le
return true; return true;
} }
false false
} }
#[cfg(test)] #[cfg(test)]
@@ -433,6 +433,7 @@ 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!(*val.bytes(), b);
assert_eq!("a0e72cc948119fcb71b413cf5ada12b2b825d5133299b20a6d9325ffc3e2fbf1", mt.root.to_hex()); assert_eq!("a0e72cc948119fcb71b413cf5ada12b2b825d5133299b20a6d9325ffc3e2fbf1", mt.root.to_hex());
} }
#[test] #[test]
fn test_add_2() { fn test_add_2() {
let mut mt: MerkleTree = new(140); let mut mt: MerkleTree = new(140);
@@ -453,8 +454,8 @@ pub fn verify_proof(root: [u8;32], mp: Vec<u8>, hi: [u8;32], ht: [u8;32], num_le
let (_t, _il, b) = mt.sto.get(&val2.ht()); let (_t, _il, b) = mt.sto.get(&val2.ht());
assert_eq!(*val2.bytes(), b); assert_eq!(*val2.bytes(), b);
assert_eq!("8ac95e9c8a6fbd40bb21de7895ee35f9c8f30ca029dbb0972c02344f49462e82", mt.root.to_hex()); assert_eq!("8ac95e9c8a6fbd40bb21de7895ee35f9c8f30ca029dbb0972c02344f49462e82", mt.root.to_hex());
mt.print_full_tree();
} }
#[test] #[test]
fn test_generate_proof_and_verify_proof() { fn test_generate_proof_and_verify_proof() {
let mut mt: MerkleTree = new(140); let mut mt: MerkleTree = new(140);
@@ -483,6 +484,7 @@ pub fn verify_proof(root: [u8;32], mp: Vec<u8>, hi: [u8;32], ht: [u8;32], num_le
let v = verify_proof(mt.root, mp, val2.hi(), val2.ht(), mt.num_levels); let v = verify_proof(mt.root, mp, val2.hi(), val2.ht(), mt.num_levels);
assert_eq!(true, v); assert_eq!(true, v);
} }
#[test] #[test]
fn test_generate_proof_empty_leaf_and_verify_proof() { fn test_generate_proof_empty_leaf_and_verify_proof() {
let mut mt: MerkleTree = new(140); let mut mt: MerkleTree = new(140);
@@ -510,6 +512,7 @@ pub fn verify_proof(root: [u8;32], mp: Vec<u8>, hi: [u8;32], ht: [u8;32], num_le
let v = verify_proof(mt.root, mp, val3.hi(), EMPTYNODEVALUE, mt.num_levels); let v = verify_proof(mt.root, mp, val3.hi(), EMPTYNODEVALUE, mt.num_levels);
assert_eq!(true, v); assert_eq!(true, v);
} }
#[test] #[test]
fn test_harcoded_proofs_of_existing_leaf() { fn test_harcoded_proofs_of_existing_leaf() {
// check proof of value in leaf // check proof of value in leaf
@@ -523,6 +526,7 @@ pub fn verify_proof(root: [u8;32], mp: Vec<u8>, hi: [u8;32], ht: [u8;32], num_le
let v = verify_proof(root, mp, hi, ht, 140); let v = verify_proof(root, mp, hi, ht, 140);
assert_eq!(true, v); assert_eq!(true, v);
} }
#[test] #[test]
fn test_harcoded_proofs_of_empty_leaf() { fn test_harcoded_proofs_of_empty_leaf() {
// check proof of value in leaf // check proof of value in leaf
@@ -534,4 +538,38 @@ pub fn verify_proof(root: [u8;32], mp: Vec<u8>, hi: [u8;32], ht: [u8;32], num_le
let v = verify_proof(root, mp, hi, EMPTYNODEVALUE, 140); let v = verify_proof(root, mp, hi, EMPTYNODEVALUE, 140);
assert_eq!(true, v); 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");
}
} }

View File

@@ -2,7 +2,6 @@ use node;
use tiny_keccak::Keccak; use tiny_keccak::Keccak;
pub fn hash_vec(b: Vec<u8>) -> [u8; 32] { pub fn hash_vec(b: Vec<u8>) -> [u8; 32] {
// let mut sha3 = Keccak::new_sha3_256();
let mut sha3 = Keccak::new_keccak256(); let mut sha3 = Keccak::new_keccak256();
sha3.update(&b); sha3.update(&b);
let mut res: [u8; 32] = [0; 32]; let mut res: [u8; 32] = [0; 32];
@@ -13,7 +12,7 @@ pub fn hash_vec(b: Vec<u8>) -> [u8; 32] {
#[allow(dead_code)] #[allow(dead_code)]
pub fn get_path(num_levels: u32, hi: [u8;32]) -> Vec<bool> { pub fn get_path(num_levels: u32, hi: [u8;32]) -> Vec<bool> {
let mut path = Vec::new(); 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.push((hi[hi.len()-i/8-1] & (1 << (i%8))) > 0);
} }
path 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> { pub fn cut_path(path: &[bool], i: usize) -> Vec<bool> {
let mut path_res: Vec<bool> = Vec::new(); let mut path_res: Vec<bool> = Vec::new();
for (j, path_elem) in path.iter().enumerate() { for j in 0..path.len() {
if j >= i { if j>=i {
path_res.push(*path_elem); path_res.push(path[j]);
} }
} }
path_res 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]> { pub fn get_empties_between_i_and_pos(i: u32, pos: u32) -> Vec<[u8;32]> {
let mut sibl: Vec<[u8;32]> = Vec::new(); let mut sibl: Vec<[u8;32]> = Vec::new();
for _ in (pos..i).rev() { for _ in (pos..=i).rev() {
sibl.push(::EMPTYNODEVALUE); sibl.push(::EMPTYNODEVALUE);
} }
sibl sibl