Skip to content

Commit

Permalink
simple_hash_from_byte_slices takes a Vec instead of slice (#59)
Browse files Browse the repository at this point in the history
* simple_hash_from_byte_slices takes a Vec instead of slice

* use Vec<Vec<u8>> with inner recursion method

* simplify tests:
 direct vector initialization instead of going through &[&[u8]]

* 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.
  • Loading branch information
liamsi committed Nov 19, 2019
1 parent 10a3026 commit cf7e702
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 16 deletions.
27 changes: 18 additions & 9 deletions tendermint/src/merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,23 @@ 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 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<Vec<u8>>) -> Hash {
simple_hash_from_byte_slices_inner(byte_vecs.as_slice())
}

// recurse into subtrees
fn simple_hash_from_byte_slices_inner(byte_slices: &[Vec<u8>]) -> Hash {
let length = byte_slices.len();
match length {
0 => [0; HASH_SIZE],
1 => leaf_hash(byte_slices[0]),
1 => leaf_hash(byte_slices[0].as_slice()),
_ => {
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_inner(&byte_slices[..k]);
let right = simple_hash_from_byte_slices_inner(&byte_slices[k..]);
inner_hash(&left, &right)
}
}
Expand Down Expand Up @@ -90,8 +97,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 root = simple_hash_from_byte_slices(empty_tree);
let empty_tree: Vec<Vec<u8>> = vec![vec![]; 1];

let root = simple_hash_from_byte_vectors(empty_tree);
assert_eq!(empty_leaf_root, &root);
}

Expand All @@ -101,8 +109,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 root = simple_hash_from_byte_slices(leaf_tree);
let leaf_tree: Vec<Vec<u8>> = vec![leaf_string.as_bytes().to_vec(); 1];

let root = simple_hash_from_byte_vectors(leaf_tree);
assert_eq!(leaf_root, &root);
}

Expand Down
8 changes: 1 addition & 7 deletions tendermint/src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,12 @@ impl Set {

/// Compute the Merkle root of the validator set
pub fn hash(self) -> merkle::Hash {
// We need to get from Vec<Info> to &[&[u8]] so we can call simple_hash_from_byte_slices.
// This looks like: Vec<Info> -> Vec<Vec<u8>> -> Vec<&[u8]> -> &[&[u8]]
// Can we simplify this?
// Perhaps simple_hash_from_byteslices should take Vec<Vec<u8>> directly ?
let validator_bytes: Vec<Vec<u8>> = 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_vectors(validator_bytes)
}
}

Expand Down

0 comments on commit cf7e702

Please sign in to comment.