From fbb9875c5602811cbcfa59aa939c5cd3a71f5607 Mon Sep 17 00:00:00 2001 From: qh11 <qh11@illinois.edu> Date: Sun, 13 Feb 2022 15:35:17 -0600 Subject: [PATCH] Update merkle.rs --- src/types/merkle.rs | 73 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/src/types/merkle.rs b/src/types/merkle.rs index b63d0b8..8d4385e 100755 --- a/src/types/merkle.rs +++ b/src/types/merkle.rs @@ -1,29 +1,92 @@ use super::hash::{Hashable, H256}; +use ring::digest; +use std::collections::VecDeque; + + /// A Merkle tree. #[derive(Debug, Default)] pub struct MerkleTree { + nodes: VecDeque<VecDeque<H256>>, } + impl MerkleTree { pub fn new<T>(data: &[T]) -> Self where T: Hashable, { - unimplemented!() + let curr_size = data.len(); + let mut nodes : VecDeque<VecDeque<H256>> = VecDeque::new(); + let mut deque : VecDeque<H256> = VecDeque::new(); + for datum in data { + deque.push_back(datum.hash()); + } + if curr_size % 2 != 0 { + deque.push_back(data[curr_size - 1].hash()); + } + nodes.push_back(deque); + loop { + if nodes[0].len() == 1 { + return Self{ + nodes: nodes, + } + } + deque = VecDeque::new(); + let curr_len = nodes[0].len(); + for i in (1..curr_len).step_by(2) { + let left_hash = nodes[0][i-1]; + let right_hash = nodes[0][i]; + let curr_hash : H256 = hash_from(&left_hash, &right_hash); + deque.push_back(curr_hash); + } + if deque.len() != 1 && deque.len() % 2 == 1 { + deque.push_back(deque[deque.len()-1]); + } + nodes.push_front(deque); + } } pub fn root(&self) -> H256 { - unimplemented!() + self.nodes[0][0] } /// Returns the Merkle Proof of data at index i pub fn proof(&self, index: usize) -> Vec<H256> { - unimplemented!() + let mut result : Vec<H256> = Vec::new(); + let mut pos = index; + for i in (1..self.nodes.len()).rev(){ + if pos % 2 == 1{ + result.push(self.nodes[i][pos-1]); + } else { + result.push(self.nodes[i][pos+1]); + } + pos /= 2; + } + result } + +} + +fn hash_from(left: &H256, right: &H256) -> H256{ + let mut combined = [0u8; 64]; + combined[..32].copy_from_slice(left.as_ref()); + combined[32..64].copy_from_slice(right.as_ref()); + digest::digest(&digest::SHA256, &combined).into() } /// Verify that the datum hash with a vector of proofs will produce the Merkle root. Also need the /// index of datum and `leaf_size`, the total number of leaves. pub fn verify(root: &H256, datum: &H256, proof: &[H256], index: usize, leaf_size: usize) -> bool { - unimplemented!() + let mut curr_hash = datum.clone(); + let mut pos = index; + for hash in proof{ + if pos % 2 == 1{ + curr_hash = hash_from(&hash, &curr_hash); + } else { + curr_hash = hash_from(&curr_hash, &hash); + } + pos /= 2; + } + curr_hash == *root + } // DO NOT CHANGE THIS COMMENT, IT IS FOR AUTOGRADER. BEFORE TEST @@ -80,4 +143,4 @@ mod tests { } } -// DO NOT CHANGE THIS COMMENT, IT IS FOR AUTOGRADER. AFTER TEST \ No newline at end of file +// DO NOT CHANGE THIS COMMENT, IT IS FOR AUTOGRADER. AFTER TEST -- GitLab