From 6665e8e8ddf9bfa31f20ccc9576146c19aa3069f Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Fri, 8 Nov 2019 13:34:38 +0100 Subject: [PATCH 1/7] simple_hash_from_byte_slices takes a Vec instead of slice --- tendermint/src/merkle.rs | 21 ++++++++++++--------- tendermint/src/validator.rs | 6 ++---- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/tendermint/src/merkle.rs b/tendermint/src/merkle.rs index f0b28efff..f05dfce13 100644 --- a/tendermint/src/merkle.rs +++ b/tendermint/src/merkle.rs @@ -8,16 +8,16 @@ pub const HASH_SIZE: usize = 32; /// Hash is the output of the cryptographic digest function pub type Hash = [u8; HASH_SIZE]; -/// Compute a simple Merkle root from the arbitrary sized byte slices -pub fn simple_hash_from_byte_slices(byte_slices: &[&[u8]]) -> Hash { +/// Compute a simple Merkle root from the arbitrary byte arrays +pub fn simple_hash_from_byte_slices(byte_slices: &Vec>) -> Hash { let length = byte_slices.len(); match length { 0 => [0; HASH_SIZE], - 1 => leaf_hash(byte_slices[0]), + 1 => leaf_hash(&byte_slices[0]), _ => { let k = get_split_point(length); - let left = simple_hash_from_byte_slices(&byte_slices[..k]); - let right = simple_hash_from_byte_slices(&byte_slices[k..]); + let left = simple_hash_from_byte_slices(&byte_slices[0..k].to_vec()); + let right = simple_hash_from_byte_slices(&byte_slices[k..].to_vec()); inner_hash(&left, &right) } } @@ -34,11 +34,11 @@ fn get_split_point(length: usize) -> usize { } // tmhash(0x00 || leaf) -fn leaf_hash(bytes: &[u8]) -> Hash { +fn leaf_hash(bytes: &Vec) -> Hash { // make a new array starting with 0 and copy in the bytes let mut leaf_bytes = Vec::with_capacity(bytes.len() + 1); leaf_bytes.push(0x00); - leaf_bytes.extend_from_slice(bytes); + leaf_bytes.extend_from_slice(&bytes); // hash it ! let digest = Sha256::digest(&leaf_bytes); @@ -91,7 +91,8 @@ mod tests { "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d"; let empty_leaf_root = &hex::decode(empty_leaf_root_hex).unwrap(); let empty_tree: &[&[u8]] = &[&[]]; - let root = simple_hash_from_byte_slices(empty_tree); + let empty_tree_vec = &empty_tree.to_vec().into_iter().map(|x| x.to_vec().clone()).collect(); + let root = simple_hash_from_byte_slices(empty_tree_vec); assert_eq!(empty_leaf_root, &root); } @@ -102,7 +103,9 @@ mod tests { let leaf_root = &hex::decode(leaf_root_hex).unwrap(); let leaf_tree: &[&[u8]] = &[leaf_string.as_bytes()]; - let root = simple_hash_from_byte_slices(leaf_tree); + let leaf_t_vec = &leaf_tree.to_vec().into_iter().map(|x| x.to_vec()).collect(); + + let root = simple_hash_from_byte_slices(leaf_t_vec); assert_eq!(leaf_root, &root); } diff --git a/tendermint/src/validator.rs b/tendermint/src/validator.rs index f7c2dc8e5..1d417f381 100644 --- a/tendermint/src/validator.rs +++ b/tendermint/src/validator.rs @@ -25,14 +25,12 @@ impl Set { // This looks like: Vec -> Vec> -> Vec<&[u8]> -> &[&[u8]] // Can we simplify this? // Perhaps simple_hash_from_byteslices should take Vec> directly ? - let validator_bytes: Vec> = self + let validator_bytes: &Vec> = &self .validators .into_iter() .map(|x| x.hash_bytes()) .collect(); - let validator_byteslices: Vec<&[u8]> = - (&validator_bytes).iter().map(|x| x.as_slice()).collect(); - merkle::simple_hash_from_byte_slices(validator_byteslices.as_slice()) + merkle::simple_hash_from_byte_slices(validator_bytes) } } From a6fcfaeb90e01ba52e6c9eb36519fd5e58fc673b Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Fri, 8 Nov 2019 13:36:22 +0100 Subject: [PATCH 2/7] cargo fmt --- tendermint/src/merkle.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tendermint/src/merkle.rs b/tendermint/src/merkle.rs index f05dfce13..3fc8eb349 100644 --- a/tendermint/src/merkle.rs +++ b/tendermint/src/merkle.rs @@ -91,7 +91,11 @@ mod tests { "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d"; let empty_leaf_root = &hex::decode(empty_leaf_root_hex).unwrap(); let empty_tree: &[&[u8]] = &[&[]]; - let empty_tree_vec = &empty_tree.to_vec().into_iter().map(|x| x.to_vec().clone()).collect(); + let empty_tree_vec = &empty_tree + .to_vec() + .into_iter() + .map(|x| x.to_vec().clone()) + .collect(); let root = simple_hash_from_byte_slices(empty_tree_vec); assert_eq!(empty_leaf_root, &root); } From e34f1b6fd7d77cd56dd9236ce45937cbfcbddbe9 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Sat, 9 Nov 2019 11:59:27 +0100 Subject: [PATCH 3/7] WIP: pass in Vec instead of &Vec - work in progress as we might want to let an inner function for the recursion - also we might simply want to use From to consume (or create a Vec) instead of changing the method signature (as suggested here: https://github.com/interchainio/tendermint-rs/issues/57#issuecomment-551925444) --- tendermint/src/merkle.rs | 14 +++++++------- tendermint/src/validator.rs | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tendermint/src/merkle.rs b/tendermint/src/merkle.rs index 3fc8eb349..3492642c3 100644 --- a/tendermint/src/merkle.rs +++ b/tendermint/src/merkle.rs @@ -9,15 +9,15 @@ pub const HASH_SIZE: usize = 32; pub type Hash = [u8; HASH_SIZE]; /// Compute a simple Merkle root from the arbitrary byte arrays -pub fn simple_hash_from_byte_slices(byte_slices: &Vec>) -> Hash { +pub fn simple_hash_from_byte_slices(byte_slices: Vec>) -> Hash { let length = byte_slices.len(); match length { 0 => [0; HASH_SIZE], - 1 => leaf_hash(&byte_slices[0]), + 1 => leaf_hash(byte_slices[0].to_vec()), _ => { let k = get_split_point(length); - let left = simple_hash_from_byte_slices(&byte_slices[0..k].to_vec()); - let right = simple_hash_from_byte_slices(&byte_slices[k..].to_vec()); + let left = simple_hash_from_byte_slices(byte_slices[0..k].to_vec()); + let right = simple_hash_from_byte_slices(byte_slices[k..].to_vec()); inner_hash(&left, &right) } } @@ -34,7 +34,7 @@ fn get_split_point(length: usize) -> usize { } // tmhash(0x00 || leaf) -fn leaf_hash(bytes: &Vec) -> Hash { +fn leaf_hash(bytes: Vec) -> Hash { // make a new array starting with 0 and copy in the bytes let mut leaf_bytes = Vec::with_capacity(bytes.len() + 1); leaf_bytes.push(0x00); @@ -91,7 +91,7 @@ mod tests { "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d"; let empty_leaf_root = &hex::decode(empty_leaf_root_hex).unwrap(); let empty_tree: &[&[u8]] = &[&[]]; - let empty_tree_vec = &empty_tree + let empty_tree_vec = empty_tree .to_vec() .into_iter() .map(|x| x.to_vec().clone()) @@ -107,7 +107,7 @@ mod tests { let leaf_root = &hex::decode(leaf_root_hex).unwrap(); let leaf_tree: &[&[u8]] = &[leaf_string.as_bytes()]; - let leaf_t_vec = &leaf_tree.to_vec().into_iter().map(|x| x.to_vec()).collect(); + let leaf_t_vec = leaf_tree.to_vec().into_iter().map(|x| x.to_vec()).collect(); let root = simple_hash_from_byte_slices(leaf_t_vec); assert_eq!(leaf_root, &root); diff --git a/tendermint/src/validator.rs b/tendermint/src/validator.rs index 1d417f381..c672dfff6 100644 --- a/tendermint/src/validator.rs +++ b/tendermint/src/validator.rs @@ -25,7 +25,7 @@ impl Set { // This looks like: Vec -> Vec> -> Vec<&[u8]> -> &[&[u8]] // Can we simplify this? // Perhaps simple_hash_from_byteslices should take Vec> directly ? - let validator_bytes: &Vec> = &self + let validator_bytes: Vec> = self .validators .into_iter() .map(|x| x.hash_bytes()) From d0e5e2716270b623e98db7f553d309da359e85c3 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Sat, 9 Nov 2019 13:26:02 +0100 Subject: [PATCH 4/7] use Vec> with inner recursion method --- tendermint/src/merkle.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tendermint/src/merkle.rs b/tendermint/src/merkle.rs index 3492642c3..accbc1cae 100644 --- a/tendermint/src/merkle.rs +++ b/tendermint/src/merkle.rs @@ -10,14 +10,19 @@ pub type Hash = [u8; HASH_SIZE]; /// Compute a simple Merkle root from the arbitrary byte arrays pub fn simple_hash_from_byte_slices(byte_slices: Vec>) -> Hash { + simple_hash_from_byte_slices_inner(byte_slices.as_slice()) +} + +// recurse into subtrees +fn simple_hash_from_byte_slices_inner(byte_slices: &[Vec]) -> Hash { let length = byte_slices.len(); match length { 0 => [0; HASH_SIZE], - 1 => leaf_hash(byte_slices[0].to_vec()), + 1 => leaf_hash(byte_slices[0].as_slice()), _ => { let k = get_split_point(length); - let left = simple_hash_from_byte_slices(byte_slices[0..k].to_vec()); - let right = simple_hash_from_byte_slices(byte_slices[k..].to_vec()); + let left = simple_hash_from_byte_slices_inner(&byte_slices[..k]); + let right = simple_hash_from_byte_slices_inner(&byte_slices[k..]); inner_hash(&left, &right) } } @@ -34,11 +39,11 @@ fn get_split_point(length: usize) -> usize { } // tmhash(0x00 || leaf) -fn leaf_hash(bytes: Vec) -> Hash { +fn leaf_hash(bytes: &[u8]) -> Hash { // make a new array starting with 0 and copy in the bytes let mut leaf_bytes = Vec::with_capacity(bytes.len() + 1); leaf_bytes.push(0x00); - leaf_bytes.extend_from_slice(&bytes); + leaf_bytes.extend_from_slice(bytes); // hash it ! let digest = Sha256::digest(&leaf_bytes); From be377fa97cb365b7a7c916abb6664ea991186588 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Sat, 9 Nov 2019 15:15:43 +0100 Subject: [PATCH 5/7] simplify tests: direct vector initialization instead of going through &[&[u8]] --- tendermint/src/merkle.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/tendermint/src/merkle.rs b/tendermint/src/merkle.rs index accbc1cae..e289d73a8 100644 --- a/tendermint/src/merkle.rs +++ b/tendermint/src/merkle.rs @@ -95,13 +95,9 @@ mod tests { let empty_leaf_root_hex = "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d"; let empty_leaf_root = &hex::decode(empty_leaf_root_hex).unwrap(); - let empty_tree: &[&[u8]] = &[&[]]; - let empty_tree_vec = empty_tree - .to_vec() - .into_iter() - .map(|x| x.to_vec().clone()) - .collect(); - let root = simple_hash_from_byte_slices(empty_tree_vec); + let empty_tree: Vec> = vec![vec![]; 1]; + + let root = simple_hash_from_byte_slices(empty_tree); assert_eq!(empty_leaf_root, &root); } @@ -111,10 +107,9 @@ mod tests { let leaf_string = "L123456"; let leaf_root = &hex::decode(leaf_root_hex).unwrap(); - let leaf_tree: &[&[u8]] = &[leaf_string.as_bytes()]; - let leaf_t_vec = leaf_tree.to_vec().into_iter().map(|x| x.to_vec()).collect(); + let leaf_tree: Vec> = vec![leaf_string.as_bytes().to_vec(); 1]; - let root = simple_hash_from_byte_slices(leaf_t_vec); + let root = simple_hash_from_byte_slices(leaf_tree); assert_eq!(leaf_root, &root); } From b4478b8fd30a6953e7b3a0a336cb0eaa002b7a55 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Sat, 9 Nov 2019 18:11:56 +0100 Subject: [PATCH 6/7] remove obsolete comment --- tendermint/src/validator.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tendermint/src/validator.rs b/tendermint/src/validator.rs index c672dfff6..8cafe386e 100644 --- a/tendermint/src/validator.rs +++ b/tendermint/src/validator.rs @@ -21,10 +21,6 @@ impl Set { /// Compute the Merkle root of the validator set pub fn hash(self) -> merkle::Hash { - // We need to get from Vec to &[&[u8]] so we can call simple_hash_from_byte_slices. - // This looks like: Vec -> Vec> -> Vec<&[u8]> -> &[&[u8]] - // Can we simplify this? - // Perhaps simple_hash_from_byteslices should take Vec> directly ? let validator_bytes: Vec> = self .validators .into_iter() From 937ba676fd4fb996c1c2f2c086bf3e8b513ebc3d Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Sat, 16 Nov 2019 12:34:29 +0100 Subject: [PATCH 7/7] Rename simple_hash_from_byte_slices to simple_hash_from_byte_vectors The method that computes the root from arbitrary given bytes doesn't take slices but Rust's array-type: vector. Also, update comment. --- tendermint/src/merkle.rs | 12 +++++++----- tendermint/src/validator.rs | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tendermint/src/merkle.rs b/tendermint/src/merkle.rs index e289d73a8..f34f0cc5f 100644 --- a/tendermint/src/merkle.rs +++ b/tendermint/src/merkle.rs @@ -8,9 +8,11 @@ pub const HASH_SIZE: usize = 32; /// Hash is the output of the cryptographic digest function pub type Hash = [u8; HASH_SIZE]; -/// Compute a simple Merkle root from the arbitrary byte arrays -pub fn simple_hash_from_byte_slices(byte_slices: Vec>) -> Hash { - simple_hash_from_byte_slices_inner(byte_slices.as_slice()) +/// Compute a simple Merkle root from vectors of arbitrary byte vectors. +/// The leaves of the tree are the bytes of the given byte vectors in +/// the given order. +pub fn simple_hash_from_byte_vectors(byte_vecs: Vec>) -> Hash { + simple_hash_from_byte_slices_inner(byte_vecs.as_slice()) } // recurse into subtrees @@ -97,7 +99,7 @@ mod tests { let empty_leaf_root = &hex::decode(empty_leaf_root_hex).unwrap(); let empty_tree: Vec> = vec![vec![]; 1]; - let root = simple_hash_from_byte_slices(empty_tree); + let root = simple_hash_from_byte_vectors(empty_tree); assert_eq!(empty_leaf_root, &root); } @@ -109,7 +111,7 @@ mod tests { let leaf_root = &hex::decode(leaf_root_hex).unwrap(); let leaf_tree: Vec> = vec![leaf_string.as_bytes().to_vec(); 1]; - let root = simple_hash_from_byte_slices(leaf_tree); + let root = simple_hash_from_byte_vectors(leaf_tree); assert_eq!(leaf_root, &root); } diff --git a/tendermint/src/validator.rs b/tendermint/src/validator.rs index 8cafe386e..f936de8a9 100644 --- a/tendermint/src/validator.rs +++ b/tendermint/src/validator.rs @@ -26,7 +26,7 @@ impl Set { .into_iter() .map(|x| x.hash_bytes()) .collect(); - merkle::simple_hash_from_byte_slices(validator_bytes) + merkle::simple_hash_from_byte_vectors(validator_bytes) } }