use ethrex_common::H256;
use ethrex_crypto::keccak::Keccak256;
use lambdaworks_crypto::merkle_tree::{merkle::MerkleTree, traits::IsMerkleTreeBackend};
#[derive(Default, Debug, PartialEq, Eq)]
struct TreeData(pub H256);
impl IsMerkleTreeBackend for TreeData {
type Data = TreeData;
type Node = [u8; 32];
fn hash_data(leaf: &Self::Data) -> Self::Node {
leaf.0.to_fixed_bytes()
}
fn hash_new_parent(child_1: &Self::Node, child_2: &Self::Node) -> Self::Node {
let mut hasher = Keccak256::new();
if child_1 < child_2 {
hasher.update(child_1);
hasher.update(child_2);
} else {
hasher.update(child_2);
hasher.update(child_1);
}
hasher.finalize()
}
}
fn build_tree(hashes: &[H256]) -> Option<MerkleTree<TreeData>> {
let data: Vec<TreeData> = hashes.iter().copied().map(TreeData).collect();
MerkleTree::<TreeData>::build(&data)
}
pub fn compute_merkle_root(hashes: &[H256]) -> H256 {
let Some(tree) = build_tree(hashes) else {
return H256::zero();
};
H256::from(tree.root)
}
pub fn compute_merkle_proof(hashes: &[H256], index: usize) -> Option<Vec<H256>> {
Some(
build_tree(hashes)?
.get_proof_by_pos(index)?
.merkle_path
.iter()
.map(H256::from)
.collect(),
)
}