Merge pull request #262 from johnsBeharry/205-merkle-root

Build tree and get merkle_root from hashed inputs  (#205)
This commit is contained in:
Paul Hauner 2019-05-07 16:10:08 +10:00 committed by GitHub
commit 5a8840b360
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -8,6 +8,36 @@ pub fn hash(input: &[u8]) -> Vec<u8> {
result
}
/// Get merkle root of some hashed values - the input leaf nodes is expected to already be hashed
/// Outputs a `Vec<u8>` byte array of the merkle root given a set of leaf node values.
pub fn merkle_root(values: &[Vec<u8>]) -> Option<Vec<u8>> {
let values_len = values.len();
// check size of vector > 0 and ^ 2
if values.is_empty() || !values_len.is_power_of_two() {
return None;
}
// vector to store hashes
// filled with 0 as placeholders
let mut o: Vec<Vec<u8>> = vec![vec![0]; values_len];
// append values to the end
o.append(&mut values.to_vec());
// traverse backwards as values are at the end
// then fill placeholders with a hash of two leaf nodes
for i in (0..values_len).rev() {
let mut current_value: Vec<u8> = o[i * 2].clone();
current_value.append(&mut o[i * 2 + 1].clone());
o[i] = hash(&current_value[..]);
}
// the root hash will be at index 1
return Some(o[1].clone());
}
#[cfg(test)]
mod tests {
use super::*;
@ -25,4 +55,51 @@ mod tests {
];
assert_eq!(expected, output.as_slice());
}
#[test]
fn test_merkle_root() {
// hash the leaf nodes
let mut input = vec![
hash("a".as_bytes()),
hash("b".as_bytes()),
hash("c".as_bytes()),
hash("d".as_bytes()),
];
// generate a merkle tree and return the root
let output = merkle_root(&input[..]);
// create merkle root manually
let mut leaf_1_2: Vec<u8> = input[0].clone(); // a
leaf_1_2.append(&mut input[1].clone()); // b
let mut leaf_3_4: Vec<u8> = input[2].clone(); // c
leaf_3_4.append(&mut input[3].clone()); // d
let node_1 = hash(&leaf_1_2[..]);
let node_2 = hash(&leaf_3_4[..]);
let mut root: Vec<u8> = node_1.clone(); // ab
root.append(&mut node_2.clone()); // cd
let expected = hash(&root[..]);
assert_eq!(&expected[..], output.unwrap().as_slice());
}
#[test]
fn test_empty_input_merkle_root() {
let input = vec![];
let output = merkle_root(&input[..]);
assert_eq!(None, output);
}
#[test]
fn test_odd_leaf_merkle_root() {
let input = vec![
hash("a".as_bytes()),
hash("b".as_bytes()),
hash("a".as_bytes()),
];
let output = merkle_root(&input[..]);
assert_eq!(None, output);
}
}