use crate::primitives::keccak256;
pub fn merkle_root(mut leaves: impl AsMut<[[u8; 32]]>) -> Option<[u8; 32]> {
let mut leaves = leaves.as_mut();
let mut pair_buf = [0; 64];
let mut pair = |left: &[u8; 32], right: &[u8; 32]| {
pair_buf[.. 32].copy_from_slice(left);
pair_buf[32 ..].copy_from_slice(right);
keccak256(pair_buf)
};
match leaves.len() {
0 => None,
1 => Some(leaves[0]),
2 => Some(pair(&leaves[0], &leaves[1])),
_ => {
let mut low_pow_2 = {
let highest_bit_set = usize::BITS - leaves.len().leading_zeros();
1 << (highest_bit_set - 1)
};
while leaves.len() != 1 {
if leaves.len() == low_pow_2 {
low_pow_2 >>= 1;
}
let overage = leaves.len() - low_pow_2;
let start = low_pow_2 - overage;
for i in 0 .. overage {
let left = leaves[start + (2 * i)];
let right = leaves[start + (2 * i) + 1];
leaves[start + i] = pair(&left, &right);
}
leaves = &mut leaves[.. low_pow_2];
}
Some(leaves[0])
}
}
}