use crate::merkle_node::MerkleNode;
use crate::MerkleProof;
use sha2::{Digest, Sha256};
#[derive(Clone)]
pub struct MerkleTree {
root: Option<MerkleNode>,
leaves: Vec<MerkleNode>,
}
impl MerkleTree {
pub fn new(data_items: Vec<Vec<u8>>) -> Self {
if data_items.is_empty() {
return MerkleTree {
root: None,
leaves: Vec::new(),
};
}
let mut leaves: Vec<MerkleNode> =
data_items.into_iter().map(MerkleNode::new_leaf).collect();
if leaves.len() == 1 {
let leaf_copy = leaves[0].clone();
return MerkleTree {
root: Some(leaf_copy),
leaves,
};
}
if leaves.len() % 2 == 1 {
leaves.push(leaves.last().unwrap().clone());
}
let leaves_copy = leaves.clone();
let root = Some(MerkleTree::build_tree(leaves));
MerkleTree {
root,
leaves: leaves_copy,
}
}
fn build_tree(nodes: Vec<MerkleNode>) -> MerkleNode {
if nodes.len() == 1 {
return nodes[0].clone();
}
let mut next_level = Vec::new();
for chunk in nodes.chunks(2) {
if chunk.len() == 2 {
let branch = MerkleNode::new_branch(chunk[0].clone(), chunk[1].clone());
next_level.push(branch);
} else {
next_level.push(chunk[0].clone());
}
}
MerkleTree::build_tree(next_level)
}
pub fn root_hash(&self) -> Option<Vec<u8>> {
self.root.as_ref().map(|node| node.hash())
}
pub fn root_hash_hex(&self) -> String {
match self.root_hash() {
Some(hash) => hex::encode(&hash),
None => String::from("Empty tree"),
}
}
pub fn generate_proof(&self, data: &[u8]) -> Option<MerkleProof> {
let target_hash = Sha256::digest(data).to_vec();
let leaf_index = self.leaves.iter().position(|node| match node {
MerkleNode::Leaf { hash, .. } => hash == &target_hash,
_ => false,
})?;
let mut proof = Vec::new();
let mut index = leaf_index;
let mut level_size = self.leaves.len();
let mut level_nodes = self.leaves.clone();
while level_size > 1 {
let is_left = index % 2 == 0;
let sibling_idx = if is_left { index + 1 } else { index - 1 };
if sibling_idx < level_nodes.len() {
proof.push((level_nodes[sibling_idx].hash(), !is_left));
}
index /= 2;
level_size = (level_size + 1) / 2;
let mut next_level = Vec::new();
for chunk in level_nodes.chunks(2) {
if chunk.len() == 2 {
let branch = MerkleNode::new_branch(chunk[0].clone(), chunk[1].clone());
next_level.push(branch);
} else {
next_level.push(chunk[0].clone());
}
}
level_nodes = next_level;
}
Some(proof)
}
pub fn verify_proof(data: &[u8], proof: &MerkleProof, root_hash: &[u8]) -> bool {
let mut current_hash = Sha256::digest(data).to_vec();
for (sibling_hash, is_left) in proof {
let mut hasher = Sha256::new();
if *is_left {
hasher.update(sibling_hash);
hasher.update(¤t_hash);
} else {
hasher.update(¤t_hash);
hasher.update(sibling_hash);
}
current_hash = hasher.finalize().to_vec();
}
current_hash == root_hash
}
pub fn len(&self) -> usize {
self.leaves.len()
}
pub fn is_empty(&self) -> bool {
self.leaves.is_empty()
}
pub fn print_tree(&self) {
if let Some(root) = &self.root {
println!("Merkle Tree Structure:");
Self::print_node(root, 0);
} else {
println!("Empty tree");
}
}
fn print_node(node: &MerkleNode, indent: usize) {
let indent_str = " ".repeat(indent * 2);
match node {
MerkleNode::Leaf { data, hash } => {
println!(
"{}Leaf: data={:?}, hash={}",
indent_str,
String::from_utf8_lossy(data),
hex::encode(&hash[0..4])
); }
MerkleNode::Branch { left, right, hash } => {
println!("{}Branch: hash={}", indent_str, hex::encode(&hash[0..4]));
Self::print_node(left, indent + 1);
Self::print_node(right, indent + 1);
}
}
}
}