Browse Source

v.hi() & ht(), add harcoded tests, update readme

master
arnaucube 5 years ago
parent
commit
fc5983e0c3
4 changed files with 87 additions and 25 deletions
  1. +1
    -0
      Cargo.toml
  2. +30
    -0
      README.md
  3. +54
    -23
      src/lib.rs
  4. +2
    -2
      src/utils.rs

+ 1
- 0
Cargo.toml

@ -9,3 +9,4 @@ rustc-hex = "1.0.0"
bitreader = "0.3.1" bitreader = "0.3.1"
arrayref = "0.3.5" arrayref = "0.3.5"
byteorder = "1.3.1" byteorder = "1.3.1"
hex = "0.3.2"

+ 30
- 0
README.md

@ -2,3 +2,33 @@
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.
## Usage
Create new tree:
```rust
let mut mt: MerkleTree = new(140);
```
Add value to leaf:
```rust
let val = TestValue {
bytes: "this is a test leaf".as_bytes().to_vec(),
index_length: 15,
};
mt.add(&val);
```
Get proof:
```rust
let mp = mt.generate_proof(val.hi());
```
Verify proof:
```rust
// check if the value exist
let v = verify_proof(mt.root, mp, val.hi(), val.ht(), mt.num_levels);
// check if the don't value exist
let v = verify_proof(mt.root, mp, val.hi(), EMPTYNODEVALUE, mt.num_levels);
```

+ 54
- 23
src/lib.rs

@ -7,6 +7,8 @@ extern crate tiny_keccak;
extern crate rustc_hex; extern crate rustc_hex;
extern crate hex;
mod utils; mod utils;
mod node; mod node;
@ -23,6 +25,8 @@ pub struct TestValue {
pub trait Value { pub trait Value {
fn bytes(&self) -> &Vec<u8>; fn bytes(&self) -> &Vec<u8>;
fn index_length(&self) -> u32; fn index_length(&self) -> u32;
fn hi(&self) -> [u8;32];
fn ht(&self) -> [u8;32];
} }
impl Value for TestValue { impl Value for TestValue {
fn bytes(&self) -> &Vec<u8> { fn bytes(&self) -> &Vec<u8> {
@ -31,6 +35,12 @@ impl Value for TestValue {
fn index_length(&self) -> u32 { fn index_length(&self) -> u32 {
self.index_length self.index_length
} }
fn hi(&self) -> [u8;32] {
utils::hash_vec(self.bytes().to_vec().split_at(self.index_length() as usize).0.to_vec())
}
fn ht(&self) -> [u8;32] {
utils::hash_vec(self.bytes().to_vec())
}
} }
#[allow(dead_code)] #[allow(dead_code)]
@ -94,20 +104,19 @@ impl MerkleTree {
// println!("adding value: {:?}", v.bytes()); // println!("adding value: {:?}", v.bytes());
// add the leaf that we are adding // add the leaf that we are adding
self.sto.insert(utils::hash_vec(v.bytes().to_vec()), TYPENODEVALUE, v.index_length(), &mut v.bytes().to_vec());
self.sto.insert(v.ht(), TYPENODEVALUE, v.index_length(), &mut v.bytes().to_vec());
let index = v.index_length() as usize; let index = v.index_length() as usize;
let hi = utils::hash_vec(v.bytes()[..index].to_vec());
let ht = utils::hash_vec(v.bytes().to_vec());
let hi = v.hi();
let ht = v.ht();
let path = utils::get_path(self.num_levels, hi); let path = utils::get_path(self.num_levels, hi);
let mut siblings: Vec<[u8;32]> = Vec::new(); let mut siblings: Vec<[u8;32]> = Vec::new();
let mut node_hash = self.root; let mut node_hash = self.root;
for i in (0..self.num_levels-1).rev() {
for i in (0..=self.num_levels-2).rev() {
// get node // get node
// let (t, il, node_bytes) = self.sto.get(&utils::hash_vec(node_hash.to_vec()));
let (t, il, node_bytes) = self.sto.get(&node_hash); let (t, il, node_bytes) = self.sto.get(&node_hash);
if t == TYPENODEFINAL { if t == TYPENODEFINAL {
let hi_child = utils::hash_vec(node_bytes.to_vec().split_at(il as usize).0.to_vec()); let hi_child = utils::hash_vec(node_bytes.to_vec().split_at(il as usize).0.to_vec());
@ -119,7 +128,7 @@ impl MerkleTree {
} }
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, &mut node_bytes.to_vec());
let final_node_2_hash = utils::calc_hash_from_leaf_and_level(pos_diff, &path, utils::hash_vec(v.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(), &mut v.bytes().to_vec());
// parent node // parent node
@ -137,6 +146,7 @@ impl MerkleTree {
for empty in &empties { for empty in &empties {
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.clone(), parent_node.ht(), TYPENODENORMAL, 0, &mut parent_node.bytes().to_vec());
return; return;
@ -155,18 +165,18 @@ impl MerkleTree {
siblings.push(*array_ref!(sibling, 0, 32)); siblings.push(*array_ref!(sibling, 0, 32));
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, utils::hash_vec(v.bytes().to_vec()));
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(), &mut 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, utils::hash_vec(v.bytes().to_vec()));
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.clone(), final_node_hash, TYPENODEFINAL, v.index_length(), &mut v.bytes().to_vec());
return; return;
} }
} }
self.root = self.replace_leaf(path, siblings, utils::hash_vec(v.bytes().to_vec()), TYPENODEVALUE, v.index_length(), &mut v.bytes().to_vec());
self.root = self.replace_leaf(path, siblings, v.ht(), TYPENODEVALUE, v.index_length(), &mut v.bytes().to_vec());
} }
#[allow(dead_code)] #[allow(dead_code)]
@ -198,7 +208,7 @@ impl MerkleTree {
pub fn get_value_in_pos(&self, hi: [u8;32]) -> Vec<u8> { pub fn get_value_in_pos(&self, hi: [u8;32]) -> Vec<u8> {
let path = utils::get_path(self.num_levels, hi); let path = utils::get_path(self.num_levels, hi);
let mut node_hash = self.root; let mut node_hash = self.root;
for i in (0..self.num_levels-1).rev() {
for i in (0..=self.num_levels-2).rev() {
let (t, il, node_bytes) = self.sto.get(&node_hash); let (t, il, node_bytes) = self.sto.get(&node_hash);
if t == TYPENODEFINAL { if t == TYPENODEFINAL {
let hi_node = utils::hash_vec(node_bytes.to_vec().split_at(il as usize).0.to_vec()); let hi_node = utils::hash_vec(node_bytes.to_vec().split_at(il as usize).0.to_vec());
@ -296,7 +306,7 @@ pub fn verify_proof(root: [u8;32], mp: Vec, hi: [u8;32], ht: [u8;32], num_le
let mut node_hash = ht; let mut node_hash = ht;
let mut sibling_used_pos = 0; let mut sibling_used_pos = 0;
for i in (0..num_levels-1).rev() {
for i in (0..=num_levels-2).rev() {
let sibling: [u8;32]; let sibling: [u8;32];
if (empties[empties.len()-i as usize/8-1] & (1 << (i%8))) > 0 { if (empties[empties.len()-i as usize/8-1] & (1 << (i%8))) > 0 {
sibling = siblings[sibling_used_pos]; sibling = siblings[sibling_used_pos];
@ -370,7 +380,7 @@ pub fn verify_proof(root: [u8;32], mp: Vec, hi: [u8;32], ht: [u8;32], num_le
index_length: 3, index_length: 3,
}; };
mt.add(&val); mt.add(&val);
let (_t, _il, b) = mt.sto.get(&utils::hash_vec(val.bytes().to_vec()));
let (_t, _il, b) = mt.sto.get(&val.ht());
assert_eq!(*val.bytes(), b); assert_eq!(*val.bytes(), b);
assert_eq!("a0e72cc948119fcb71b413cf5ada12b2b825d5133299b20a6d9325ffc3e2fbf1", mt.root.to_hex()); assert_eq!("a0e72cc948119fcb71b413cf5ada12b2b825d5133299b20a6d9325ffc3e2fbf1", mt.root.to_hex());
} }
@ -383,7 +393,7 @@ pub fn verify_proof(root: [u8;32], mp: Vec, hi: [u8;32], ht: [u8;32], num_le
}; };
assert_eq!("0000000000000000000000000000000000000000000000000000000000000000", mt.root.to_hex()); assert_eq!("0000000000000000000000000000000000000000000000000000000000000000", mt.root.to_hex());
mt.add(&val); mt.add(&val);
let (_t, _il, b) = mt.sto.get(&utils::hash_vec(val.bytes().to_vec()));
let (_t, _il, b) = mt.sto.get(&val.ht());
assert_eq!(*val.bytes(), b); assert_eq!(*val.bytes(), b);
assert_eq!("b4fdf8a653198f0e179ccb3af7e4fc09d76247f479d6cfc95cd92d6fda589f27", mt.root.to_hex()); assert_eq!("b4fdf8a653198f0e179ccb3af7e4fc09d76247f479d6cfc95cd92d6fda589f27", mt.root.to_hex());
let val2 = TestValue { let val2 = TestValue {
@ -391,7 +401,7 @@ pub fn verify_proof(root: [u8;32], mp: Vec, hi: [u8;32], ht: [u8;32], num_le
index_length: 15, index_length: 15,
}; };
mt.add(&val2); mt.add(&val2);
let (_t, _il, b) = mt.sto.get(&utils::hash_vec(val2.bytes().to_vec()));
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());
} }
@ -404,7 +414,7 @@ pub fn verify_proof(root: [u8;32], mp: Vec, hi: [u8;32], ht: [u8;32], num_le
}; };
assert_eq!("0000000000000000000000000000000000000000000000000000000000000000", mt.root.to_hex()); assert_eq!("0000000000000000000000000000000000000000000000000000000000000000", mt.root.to_hex());
mt.add(&val); mt.add(&val);
let (_t, _il, b) = mt.sto.get(&utils::hash_vec(val.bytes().to_vec()));
let (_t, _il, b) = mt.sto.get(&val.ht());
assert_eq!(*val.bytes(), b); assert_eq!(*val.bytes(), b);
assert_eq!("b4fdf8a653198f0e179ccb3af7e4fc09d76247f479d6cfc95cd92d6fda589f27", mt.root.to_hex()); assert_eq!("b4fdf8a653198f0e179ccb3af7e4fc09d76247f479d6cfc95cd92d6fda589f27", mt.root.to_hex());
let val2 = TestValue { let val2 = TestValue {
@ -412,17 +422,15 @@ pub fn verify_proof(root: [u8;32], mp: Vec, hi: [u8;32], ht: [u8;32], num_le
index_length: 15, index_length: 15,
}; };
mt.add(&val2); mt.add(&val2);
let (_t, _il, b) = mt.sto.get(&utils::hash_vec(val2.bytes().to_vec()));
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());
let hi = utils::hash_vec(val2.bytes().to_vec().split_at(val2.index_length as usize).0.to_vec());
let mp = mt.generate_proof(hi);
let mp = mt.generate_proof(val2.hi());
assert_eq!("0000000000000000000000000000000000000000000000000000000000000001fd8e1a60cdb23c0c7b2cf8462c99fafd905054dccb0ed75e7c8a7d6806749b6b", mp.to_hex()); assert_eq!("0000000000000000000000000000000000000000000000000000000000000001fd8e1a60cdb23c0c7b2cf8462c99fafd905054dccb0ed75e7c8a7d6806749b6b", mp.to_hex());
// verify // verify
let ht = utils::hash_vec(val2.bytes().to_vec());
let v = verify_proof(mt.root, mp, hi, 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]
@ -445,12 +453,35 @@ pub fn verify_proof(root: [u8;32], mp: Vec, hi: [u8;32], ht: [u8;32], num_le
bytes: "this is a third test leaf".as_bytes().to_vec(), bytes: "this is a third test leaf".as_bytes().to_vec(),
index_length: 15, index_length: 15,
}; };
let hi = utils::hash_vec(val3.bytes().to_vec().split_at(val3.index_length as usize).0.to_vec());
let mp = mt.generate_proof(hi);
let mp = mt.generate_proof(val3.hi());
assert_eq!("000000000000000000000000000000000000000000000000000000000000000389741fa23da77c259781ad8f4331a5a7d793eef1db7e5200ddfc8e5f5ca7ce2bfd8e1a60cdb23c0c7b2cf8462c99fafd905054dccb0ed75e7c8a7d6806749b6b", mp.to_hex()); assert_eq!("000000000000000000000000000000000000000000000000000000000000000389741fa23da77c259781ad8f4331a5a7d793eef1db7e5200ddfc8e5f5ca7ce2bfd8e1a60cdb23c0c7b2cf8462c99fafd905054dccb0ed75e7c8a7d6806749b6b", mp.to_hex());
// verify that is a proof of an empty leaf (EMPTYNODEVALUE) // verify that is a proof of an empty leaf (EMPTYNODEVALUE)
let v = verify_proof(mt.root, mp, hi, EMPTYNODEVALUE, mt.num_levels);
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
let mut root: [u8;32] = [0;32];
root.copy_from_slice(&hex::decode("7d7c5e8f4b3bf434f3d9d223359c4415e2764dd38de2e025fbf986e976a7ed3d").unwrap());
let mp = hex::decode("0000000000000000000000000000000000000000000000000000000000000002d45aada6eec346222eaa6b5d3a9260e08c9b62fcf63c72bc05df284de07e6a52").unwrap();
let mut hi: [u8;32] = [0;32];
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);
}
#[test]
fn test_harcoded_proofs_of_empty_leaf() {
// check proof of value in leaf
let mut root: [u8;32] = [0;32];
root.copy_from_slice(&hex::decode("8f021d00c39dcd768974ddfe0d21f5d13f7215bea28db1f1cb29842b111332e7").unwrap());
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); assert_eq!(true, v);
} }
} }

+ 2
- 2
src/utils.rs

@ -61,10 +61,10 @@ 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 _j in (pos..i).rev() {
for _ in (pos..i).rev() {
sibl.push(::EMPTYNODEVALUE); sibl.push(::EMPTYNODEVALUE);
} }
sibl.to_vec()
sibl
} }
#[cfg(test)] #[cfg(test)]

Loading…
Cancel
Save