From 3411f54c2e8448af0492bbca5e2ce225e5c2ab16 Mon Sep 17 00:00:00 2001 From: Johns Beharry Date: Fri, 11 Jan 2019 19:25:13 -0400 Subject: [PATCH 01/12] feat(hashing): write test for merkle_root #146 Signed-off-by: Johns Beharry --- beacon_chain/utils/hashing/src/merkle_root.rs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 beacon_chain/utils/hashing/src/merkle_root.rs diff --git a/beacon_chain/utils/hashing/src/merkle_root.rs b/beacon_chain/utils/hashing/src/merkle_root.rs new file mode 100644 index 0000000000..3251154f01 --- /dev/null +++ b/beacon_chain/utils/hashing/src/merkle_root.rs @@ -0,0 +1,29 @@ +use types::{Hash256} +use hashing::canonical_hash; + +fn merkle_root(values: Vec<>) -> Hash256 { + let o = values.len(); + + for v in &values { + canonical_hash(v.as_bytes()); + } +} + +#[cfg(test)] +mod tests { + #[test] + fn calculate_merkle_root() { + let values = vec!['abc', 'lmn', 'xyz', 'o0o']; + + let test_leaf_1 = canonical_hash(values[0]); + let test_leaf_2 = canonical_hash(values[1]); + let test_leaf_3 = canonical_hash(values[2]); + let test_leaf_4 = canonical_hash(values[3]); + let test_node_1 = canonical_hash(vec![test_leaf_1, test_leaf_2]); + let test_node_2 = canonical_hash(vec![test_leaf_3, test_leaf_4]); + let test_root = canonical_hash(vec![test_node_1, test_node_2]); + + let result = merkle_root(values); + assert_eq!(result, test_root); + } +} From 998e2ed7eba1cba6b28b09852c47118bac7511df Mon Sep 17 00:00:00 2001 From: Johns Beharry Date: Fri, 11 Jan 2019 19:45:31 -0400 Subject: [PATCH 02/12] feat(hashing): fill o with 0s placeholders #146 Signed-off-by: Johns Beharry --- beacon_chain/utils/hashing/src/merkle_root.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/beacon_chain/utils/hashing/src/merkle_root.rs b/beacon_chain/utils/hashing/src/merkle_root.rs index 3251154f01..9a05ed4507 100644 --- a/beacon_chain/utils/hashing/src/merkle_root.rs +++ b/beacon_chain/utils/hashing/src/merkle_root.rs @@ -1,8 +1,9 @@ use types::{Hash256} use hashing::canonical_hash; -fn merkle_root(values: Vec<>) -> Hash256 { - let o = values.len(); +fn merkle_root(values: Vec) -> Hash256 { + let mut o = vec![0; values.len()]; + o.append(values); for v in &values { canonical_hash(v.as_bytes()); @@ -19,8 +20,8 @@ mod tests { let test_leaf_2 = canonical_hash(values[1]); let test_leaf_3 = canonical_hash(values[2]); let test_leaf_4 = canonical_hash(values[3]); - let test_node_1 = canonical_hash(vec![test_leaf_1, test_leaf_2]); - let test_node_2 = canonical_hash(vec![test_leaf_3, test_leaf_4]); + let test_node_1 = canonical_hash(vec![test_leaf_4, test_leaf_3]); + let test_node_2 = canonical_hash(vec![test_leaf_2, test_leaf_1]); let test_root = canonical_hash(vec![test_node_1, test_node_2]); let result = merkle_root(values); From fa2bae4cc1fc2dc177358df15bfe68832051a4cf Mon Sep 17 00:00:00 2001 From: Johns Beharry Date: Sat, 12 Jan 2019 10:38:58 -0400 Subject: [PATCH 03/12] fix(hashing): reverse loop #146 Signed-off-by: Johns Beharry --- beacon_chain/utils/hashing/src/merkle_root.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/beacon_chain/utils/hashing/src/merkle_root.rs b/beacon_chain/utils/hashing/src/merkle_root.rs index 9a05ed4507..345c491c58 100644 --- a/beacon_chain/utils/hashing/src/merkle_root.rs +++ b/beacon_chain/utils/hashing/src/merkle_root.rs @@ -1,11 +1,12 @@ use types::{Hash256} use hashing::canonical_hash; +use std::iter::range_step; fn merkle_root(values: Vec) -> Hash256 { let mut o = vec![0; values.len()]; o.append(values); - for v in &values { + for v in range_step(values - 1, 0, -1) { canonical_hash(v.as_bytes()); } } From 39dc8437e80d998f831776d97321784f586c4f06 Mon Sep 17 00:00:00 2001 From: Johns Beharry Date: Wed, 23 Jan 2019 11:47:57 -0400 Subject: [PATCH 04/12] feat(merkle_root): commit changes Signed-off-by: Johns Beharry --- beacon_chain/utils/hashing/src/merkle_root.rs | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/beacon_chain/utils/hashing/src/merkle_root.rs b/beacon_chain/utils/hashing/src/merkle_root.rs index 345c491c58..11307a880e 100644 --- a/beacon_chain/utils/hashing/src/merkle_root.rs +++ b/beacon_chain/utils/hashing/src/merkle_root.rs @@ -1,29 +1,35 @@ use types::{Hash256} use hashing::canonical_hash; -use std::iter::range_step; -fn merkle_root(values: Vec) -> Hash256 { - let mut o = vec![0; values.len()]; +pub fn merkle_root(values: Vec) -> Hash256 { + let mut o: Vec<&[u8]> = vec![0; values.len()]; + let mut value_hashes = vec![]; + for v in values { + value_hashes.push(canonical_hash(v); + } + o.append(values); - for v in range_step(values - 1, 0, -1) { - canonical_hash(v.as_bytes()); + for i in (0..values.len() - 1).rev() { + canonical_hash(o[i * 2] + o[i * 2 + 1]); } + + o[1]; } #[cfg(test)] mod tests { #[test] fn calculate_merkle_root() { - let values = vec!['abc', 'lmn', 'xyz', 'o0o']; + let values = vec!["abc", "lmn", "xyz", "o0o"]; - let test_leaf_1 = canonical_hash(values[0]); - let test_leaf_2 = canonical_hash(values[1]); - let test_leaf_3 = canonical_hash(values[2]); - let test_leaf_4 = canonical_hash(values[3]); - let test_node_1 = canonical_hash(vec![test_leaf_4, test_leaf_3]); - let test_node_2 = canonical_hash(vec![test_leaf_2, test_leaf_1]); - let test_root = canonical_hash(vec![test_node_1, test_node_2]); + let test_leaf_0 = canonical_hash(values[0]); + let test_leaf_1 = canonical_hash(values[1]); + let test_leaf_2 = canonical_hash(values[2]); + let test_leaf_3 = canonical_hash(values[3]); + let test_node_0 = canonical_hash(test_leaf_3 + test_leaf_2); + let test_node_1 = canonical_hash(test_leaf_1 + test_leaf_0); + let test_root = canonical_hash(test_node_0 + test_node_0); let result = merkle_root(values); assert_eq!(result, test_root); From af87fbf2033f7fe1d85600b12cacaaa1ca761712 Mon Sep 17 00:00:00 2001 From: Johns Beharry Date: Fri, 22 Feb 2019 13:12:07 -0400 Subject: [PATCH 05/12] feat(merkle_root): hash vector of leafs to get merkle_root Signed-off-by: Johns Beharry --- eth2/utils/hashing/src/lib.rs | 75 +++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/eth2/utils/hashing/src/lib.rs b/eth2/utils/hashing/src/lib.rs index b2bd5a2798..4186e27a92 100644 --- a/eth2/utils/hashing/src/lib.rs +++ b/eth2/utils/hashing/src/lib.rs @@ -8,6 +8,31 @@ pub fn hash(input: &[u8]) -> Vec { result } +pub fn merkle_root(values: &[Vec]) -> Vec { + let values_len = values.len(); + let mut o: Vec> = vec![vec![0]; values_len]; + + o.append(&mut values.to_vec()); + + println!("o {:?}", o); + + for i in (0..values_len).rev() { + let mut current_value: Vec = o[i * 2].clone(); + current_value.append(&mut o[i * 2 + 1].clone()); + + o[i] = hash(¤t_value[..]); + println!("i {:?}", i); + print!(" "); + println!("o[i * 2] {} -- {:?}", i * 2, o[i * 2]); + print!(" "); + println!("o[i * 2 + 1] {} -- {:?}", i * 2 + 1, o[i * 2 + 1]); + } + +// println!("{:?}", o); + + o[1].clone() +} + #[cfg(test)] mod tests { use super::*; @@ -23,6 +48,56 @@ mod tests { 0x28, 0x7b, 0x56, 0xd9, 0x51, 0x7b, 0x9c, 0x94, 0x81, 0x27, 0x31, 0x9a, 0x09, 0xa7, 0xa3, 0x6d, 0xea, 0xc8, ]; + + println!("{:?}", expected); + println!("{:?}", output); assert_eq!(expected, output.as_slice()); } + + #[test] + fn test_merkle_root() { + let mut input = vec![ + "a".as_bytes().to_vec(), + "b".as_bytes().to_vec(), + "c".as_bytes().to_vec(), + "d".as_bytes().to_vec() + ]; + + let output = merkle_root(&input[..]); + + let mut leaf_1_2: Vec = input[0].clone(); // a + leaf_1_2.append(&mut input[1].clone()); // b + + let mut leaf_3_4: Vec = 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 = node_1.clone(); // ab + root.append(&mut node_2.clone()); // cd + + let mr = hash(&root[..]); + + let expected = &[183, 91, 96, 122, 144, 174, 84, 92, 97, 156, 140, 192, 66, 221, 55, 229, 234, 48, 118, 7, 61, 207, 39, 125, 150, 32, 94, 90, 19, 88, 122, 163]; + + print!(" "); + print!(" "); + print!(" "); + print!(" "); + print!(" "); + print!("origional input"); + println!("{:?}", input); + print!("NODE #1 HASH "); + println!("{:?}", node_1); + print!("NODE #2 HASH "); + println!("{:?}", node_2); + print!("ROOT HASH "); + println!("{:?}", root); + print!(" "); + println!("{:?}", expected); + + assert_eq!(expected, output.as_slice()); + + } } From 80ac60cc0e24df03eb65f2b07ce8b08659bc81d7 Mon Sep 17 00:00:00 2001 From: Johns Beharry Date: Fri, 22 Feb 2019 14:30:33 -0400 Subject: [PATCH 06/12] feat(merkle_root): calculate merkle root from leaves Signed-off-by: Johns Beharry --- eth2/utils/hashing/src/lib.rs | 52 ++++------------------------------- 1 file changed, 6 insertions(+), 46 deletions(-) diff --git a/eth2/utils/hashing/src/lib.rs b/eth2/utils/hashing/src/lib.rs index 4186e27a92..a342a2c338 100644 --- a/eth2/utils/hashing/src/lib.rs +++ b/eth2/utils/hashing/src/lib.rs @@ -14,22 +14,13 @@ pub fn merkle_root(values: &[Vec]) -> Vec { o.append(&mut values.to_vec()); - println!("o {:?}", o); - for i in (0..values_len).rev() { let mut current_value: Vec = o[i * 2].clone(); current_value.append(&mut o[i * 2 + 1].clone()); o[i] = hash(¤t_value[..]); - println!("i {:?}", i); - print!(" "); - println!("o[i * 2] {} -- {:?}", i * 2, o[i * 2]); - print!(" "); - println!("o[i * 2 + 1] {} -- {:?}", i * 2 + 1, o[i * 2 + 1]); } -// println!("{:?}", o); - o[1].clone() } @@ -48,15 +39,12 @@ mod tests { 0x28, 0x7b, 0x56, 0xd9, 0x51, 0x7b, 0x9c, 0x94, 0x81, 0x27, 0x31, 0x9a, 0x09, 0xa7, 0xa3, 0x6d, 0xea, 0xc8, ]; - - println!("{:?}", expected); - println!("{:?}", output); assert_eq!(expected, output.as_slice()); } #[test] fn test_merkle_root() { - let mut input = vec![ + let input = vec![ "a".as_bytes().to_vec(), "b".as_bytes().to_vec(), "c".as_bytes().to_vec(), @@ -65,39 +53,11 @@ mod tests { let output = merkle_root(&input[..]); - let mut leaf_1_2: Vec = input[0].clone(); // a - leaf_1_2.append(&mut input[1].clone()); // b - - let mut leaf_3_4: Vec = 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 = node_1.clone(); // ab - root.append(&mut node_2.clone()); // cd - - let mr = hash(&root[..]); - - let expected = &[183, 91, 96, 122, 144, 174, 84, 92, 97, 156, 140, 192, 66, 221, 55, 229, 234, 48, 118, 7, 61, 207, 39, 125, 150, 32, 94, 90, 19, 88, 122, 163]; - - print!(" "); - print!(" "); - print!(" "); - print!(" "); - print!(" "); - print!("origional input"); - println!("{:?}", input); - print!("NODE #1 HASH "); - println!("{:?}", node_1); - print!("NODE #2 HASH "); - println!("{:?}", node_2); - print!("ROOT HASH "); - println!("{:?}", root); - print!(" "); - println!("{:?}", expected); - + // merkle root of [[a],[b],[c],[d]] + let expected = &[ + 183, 91, 96, 122, 144, 174, 84, 92, 97, 156, 140, 192, 66, 221, 55, 229, + 234, 48, 118, 7, 61, 207, 39, 125, 150, 32, 94, 90, 19, 88, 122, 163, + ]; assert_eq!(expected, output.as_slice()); - } } From 5f9e93d3386367b348d1c94d7d95e2dd7d7406c0 Mon Sep 17 00:00:00 2001 From: Johns Beharry Date: Sun, 24 Feb 2019 04:57:12 -0400 Subject: [PATCH 07/12] chore(merkle_root): split function to it's own file Signed-off-by: Johns Beharry --- eth2/utils/hashing/src/lib.rs | 35 ----------------------- eth2/utils/hashing/src/merkle_root.rs | 41 +++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 35 deletions(-) create mode 100644 eth2/utils/hashing/src/merkle_root.rs diff --git a/eth2/utils/hashing/src/lib.rs b/eth2/utils/hashing/src/lib.rs index a342a2c338..b2bd5a2798 100644 --- a/eth2/utils/hashing/src/lib.rs +++ b/eth2/utils/hashing/src/lib.rs @@ -8,22 +8,6 @@ pub fn hash(input: &[u8]) -> Vec { result } -pub fn merkle_root(values: &[Vec]) -> Vec { - let values_len = values.len(); - let mut o: Vec> = vec![vec![0]; values_len]; - - o.append(&mut values.to_vec()); - - for i in (0..values_len).rev() { - let mut current_value: Vec = o[i * 2].clone(); - current_value.append(&mut o[i * 2 + 1].clone()); - - o[i] = hash(¤t_value[..]); - } - - o[1].clone() -} - #[cfg(test)] mod tests { use super::*; @@ -41,23 +25,4 @@ mod tests { ]; assert_eq!(expected, output.as_slice()); } - - #[test] - fn test_merkle_root() { - let input = vec![ - "a".as_bytes().to_vec(), - "b".as_bytes().to_vec(), - "c".as_bytes().to_vec(), - "d".as_bytes().to_vec() - ]; - - let output = merkle_root(&input[..]); - - // merkle root of [[a],[b],[c],[d]] - let expected = &[ - 183, 91, 96, 122, 144, 174, 84, 92, 97, 156, 140, 192, 66, 221, 55, 229, - 234, 48, 118, 7, 61, 207, 39, 125, 150, 32, 94, 90, 19, 88, 122, 163, - ]; - assert_eq!(expected, output.as_slice()); - } } diff --git a/eth2/utils/hashing/src/merkle_root.rs b/eth2/utils/hashing/src/merkle_root.rs new file mode 100644 index 0000000000..6c11d9d80e --- /dev/null +++ b/eth2/utils/hashing/src/merkle_root.rs @@ -0,0 +1,41 @@ +use crate::hash; + +pub fn merkle_root(values: &[Vec]) -> Vec { + let values_len = values.len(); + let mut o: Vec> = vec![vec![0]; values_len]; + + o.append(&mut values.to_vec()); + + for i in (0..values_len).rev() { + let mut current_value: Vec = o[i * 2].clone(); + current_value.append(&mut o[i * 2 + 1].clone()); + + o[i] = hash(¤t_value[..]); + } + + o[1].clone() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_merkle_root() { + let input = vec![ + "a".as_bytes().to_vec(), + "b".as_bytes().to_vec(), + "c".as_bytes().to_vec(), + "d".as_bytes().to_vec() + ]; + + let output = merkle_root(&input[..]); + + // merkle root of [[a],[b],[c],[d]] + let expected = &[ + 183, 91, 96, 122, 144, 174, 84, 92, 97, 156, 140, 192, 66, 221, 55, 229, + 234, 48, 118, 7, 61, 207, 39, 125, 150, 32, 94, 90, 19, 88, 122, 163, + ]; + assert_eq!(expected, output.as_slice()); + } +} From 9fbacbf9670b9346c668e8acec716da769119629 Mon Sep 17 00:00:00 2001 From: Johns Beharry Date: Wed, 27 Feb 2019 04:51:23 -0400 Subject: [PATCH 08/12] chore(merkle_root): move function into lib.rs Signed-off-by: Johns Beharry --- eth2/utils/hashing/src/lib.rs | 59 +++++++++++++++++++++++++++ eth2/utils/hashing/src/merkle_root.rs | 41 ------------------- 2 files changed, 59 insertions(+), 41 deletions(-) delete mode 100644 eth2/utils/hashing/src/merkle_root.rs diff --git a/eth2/utils/hashing/src/lib.rs b/eth2/utils/hashing/src/lib.rs index b2bd5a2798..33c31ab190 100644 --- a/eth2/utils/hashing/src/lib.rs +++ b/eth2/utils/hashing/src/lib.rs @@ -8,6 +8,33 @@ pub fn hash(input: &[u8]) -> Vec { result } +/// Generate Merkle Root +/// +/// Outputs a `Vec` byte array of the merkle root given a set of leaf node values. +/// Expects leaf nodes to already be hashed. +pub fn merkle_root(values: &[Vec]) -> Vec { + let values_len = values.len(); + + // vector to store hashes + // filled with 0 as placeholders + let mut o: Vec> = 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 = o[i * 2].clone(); + current_value.append(&mut o[i * 2 + 1].clone()); + + o[i] = hash(¤t_value[..]); + } + + // the root hash will be at index 1 + o[1].clone() +} + #[cfg(test)] mod tests { use super::*; @@ -25,4 +52,36 @@ 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 = input[0].clone(); // a + leaf_1_2.append(&mut input[1].clone()); // b + + let mut leaf_3_4: Vec = 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 = node_1.clone(); // ab + root.append(&mut node_2.clone()); // cd + + let expected = hash(&root[..]); + + assert_eq!(&expected[..], output.as_slice()); + + } } diff --git a/eth2/utils/hashing/src/merkle_root.rs b/eth2/utils/hashing/src/merkle_root.rs deleted file mode 100644 index 6c11d9d80e..0000000000 --- a/eth2/utils/hashing/src/merkle_root.rs +++ /dev/null @@ -1,41 +0,0 @@ -use crate::hash; - -pub fn merkle_root(values: &[Vec]) -> Vec { - let values_len = values.len(); - let mut o: Vec> = vec![vec![0]; values_len]; - - o.append(&mut values.to_vec()); - - for i in (0..values_len).rev() { - let mut current_value: Vec = o[i * 2].clone(); - current_value.append(&mut o[i * 2 + 1].clone()); - - o[i] = hash(¤t_value[..]); - } - - o[1].clone() -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_merkle_root() { - let input = vec![ - "a".as_bytes().to_vec(), - "b".as_bytes().to_vec(), - "c".as_bytes().to_vec(), - "d".as_bytes().to_vec() - ]; - - let output = merkle_root(&input[..]); - - // merkle root of [[a],[b],[c],[d]] - let expected = &[ - 183, 91, 96, 122, 144, 174, 84, 92, 97, 156, 140, 192, 66, 221, 55, 229, - 234, 48, 118, 7, 61, 207, 39, 125, 150, 32, 94, 90, 19, 88, 122, 163, - ]; - assert_eq!(expected, output.as_slice()); - } -} From 1c161e751f09af5b68b5511ce640b69b12b0f2e3 Mon Sep 17 00:00:00 2001 From: Johns Beharry Date: Wed, 27 Feb 2019 13:47:27 +0100 Subject: [PATCH 09/12] chore(*): remove previously cached file from restructure Signed-off-by: Johns Beharry --- beacon_chain/utils/hashing/src/merkle_root.rs | 37 ------------------- 1 file changed, 37 deletions(-) delete mode 100644 beacon_chain/utils/hashing/src/merkle_root.rs diff --git a/beacon_chain/utils/hashing/src/merkle_root.rs b/beacon_chain/utils/hashing/src/merkle_root.rs deleted file mode 100644 index 11307a880e..0000000000 --- a/beacon_chain/utils/hashing/src/merkle_root.rs +++ /dev/null @@ -1,37 +0,0 @@ -use types::{Hash256} -use hashing::canonical_hash; - -pub fn merkle_root(values: Vec) -> Hash256 { - let mut o: Vec<&[u8]> = vec![0; values.len()]; - let mut value_hashes = vec![]; - for v in values { - value_hashes.push(canonical_hash(v); - } - - o.append(values); - - for i in (0..values.len() - 1).rev() { - canonical_hash(o[i * 2] + o[i * 2 + 1]); - } - - o[1]; -} - -#[cfg(test)] -mod tests { - #[test] - fn calculate_merkle_root() { - let values = vec!["abc", "lmn", "xyz", "o0o"]; - - let test_leaf_0 = canonical_hash(values[0]); - let test_leaf_1 = canonical_hash(values[1]); - let test_leaf_2 = canonical_hash(values[2]); - let test_leaf_3 = canonical_hash(values[3]); - let test_node_0 = canonical_hash(test_leaf_3 + test_leaf_2); - let test_node_1 = canonical_hash(test_leaf_1 + test_leaf_0); - let test_root = canonical_hash(test_node_0 + test_node_0); - - let result = merkle_root(values); - assert_eq!(result, test_root); - } -} From 8429f3bff1f511315d0c215a53a5e5b2ff979a9b Mon Sep 17 00:00:00 2001 From: Johns Beharry Date: Thu, 28 Feb 2019 15:59:45 +0100 Subject: [PATCH 10/12] chore(hashing): update comments of fn merkle_root Signed-off-by: Johns Beharry --- eth2/utils/hashing/src/lib.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/eth2/utils/hashing/src/lib.rs b/eth2/utils/hashing/src/lib.rs index 33c31ab190..3f544d2c1b 100644 --- a/eth2/utils/hashing/src/lib.rs +++ b/eth2/utils/hashing/src/lib.rs @@ -8,13 +8,11 @@ pub fn hash(input: &[u8]) -> Vec { result } -/// Generate Merkle Root -/// -/// Outputs a `Vec` byte array of the merkle root given a set of leaf node values. -/// Expects leaf nodes to already be hashed. +// Get merkle root of some hashed values - the input leaf nodes is expected to already be hashed +// Outputs a `Vec` byte array of the merkle root given a set of leaf node values. pub fn merkle_root(values: &[Vec]) -> Vec { let values_len = values.len(); - + // vector to store hashes // filled with 0 as placeholders let mut o: Vec> = vec![vec![0]; values_len]; @@ -82,6 +80,5 @@ mod tests { let expected = hash(&root[..]); assert_eq!(&expected[..], output.as_slice()); - } } From 725401d2e1fc54e56fd60734d28e0612b062b0f8 Mon Sep 17 00:00:00 2001 From: Johns Beharry Date: Thu, 21 Mar 2019 02:51:49 +0100 Subject: [PATCH 11/12] test(hashing/merkle_root): write test for empty vector and odd leaf count Signed-off-by: Johns Beharry --- eth2/utils/hashing/src/lib.rs | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/eth2/utils/hashing/src/lib.rs b/eth2/utils/hashing/src/lib.rs index 3f544d2c1b..bbb37f6abe 100644 --- a/eth2/utils/hashing/src/lib.rs +++ b/eth2/utils/hashing/src/lib.rs @@ -8,11 +8,16 @@ pub fn hash(input: &[u8]) -> Vec { result } -// Get merkle root of some hashed values - the input leaf nodes is expected to already be hashed -// Outputs a `Vec` byte array of the merkle root given a set of leaf node values. -pub fn merkle_root(values: &[Vec]) -> Vec { +/// Get merkle root of some hashed values - the input leaf nodes is expected to already be hashed +/// Outputs a `Vec` byte array of the merkle root given a set of leaf node values. +pub fn merkle_root(values: &[Vec]) -> Option> { 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![vec![0]; values_len]; @@ -30,7 +35,7 @@ pub fn merkle_root(values: &[Vec]) -> Vec { } // the root hash will be at index 1 - o[1].clone() + return Some(o[1].clone()) } #[cfg(test)] @@ -79,6 +84,22 @@ mod tests { let expected = hash(&root[..]); - assert_eq!(&expected[..], output.as_slice()); + 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); } } From 06362d32d3fe1c3b0ccfe5fdee71735578fd77be Mon Sep 17 00:00:00 2001 From: Johns Beharry Date: Thu, 21 Mar 2019 11:10:15 +0100 Subject: [PATCH 12/12] chore(hashing/merkle_root): remove semi colon on returns Signed-off-by: Johns Beharry --- eth2/utils/hashing/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eth2/utils/hashing/src/lib.rs b/eth2/utils/hashing/src/lib.rs index bbb37f6abe..68e29fc9b9 100644 --- a/eth2/utils/hashing/src/lib.rs +++ b/eth2/utils/hashing/src/lib.rs @@ -15,7 +15,7 @@ pub fn merkle_root(values: &[Vec]) -> Option> { // check size of vector > 0 and ^ 2 if values.is_empty() || !values_len.is_power_of_two() { - return None + return None; } // vector to store hashes @@ -35,7 +35,7 @@ pub fn merkle_root(values: &[Vec]) -> Option> { } // the root hash will be at index 1 - return Some(o[1].clone()) + return Some(o[1].clone()); } #[cfg(test)]