use crate::primitives::{sha256d, Hash32};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MerkleRoot {
pub root: Hash32,
pub mutated: bool,
}
pub fn merkle_parent(left: &Hash32, right: &Hash32) -> Hash32 {
let mut bytes = [0; 64];
bytes[..32].copy_from_slice(left);
bytes[32..].copy_from_slice(right);
sha256d(&bytes)
}
pub fn merkle_root(leaves: &[Hash32]) -> MerkleRoot {
reduce(leaves.to_vec())
}
fn reduce(mut level: Vec<Hash32>) -> MerkleRoot {
if level.is_empty() {
return MerkleRoot {
root: [0; 32],
mutated: false,
};
}
let mut mutated = false;
while level.len() > 1 {
let width = level.len();
for i in 0..width.div_ceil(2) {
let left = level[2 * i];
let right = level.get(2 * i + 1).copied().unwrap_or(left);
mutated |= 2 * i + 1 < width && left == right;
level[i] = merkle_parent(&left, &right);
}
level.truncate(width.div_ceil(2));
}
MerkleRoot {
root: level[0],
mutated,
}
}
#[cfg(feature = "transaction")]
pub fn block_merkle_root(txs: &[crate::transaction::Transaction]) -> MerkleRoot {
reduce(txs.iter().map(|tx| tx.hash()).collect())
}