use crate::hash::{hash256, hex_to_bytes};
#[derive(Debug, Clone)]
pub struct ProofNode {
pub side: char,
pub hash: [u8; 32],
}
impl ProofNode {
pub fn from_hex(side: char, hex: &str) -> Result<Self, &'static str> {
Ok(ProofNode {
side,
hash: hex_to_bytes(hex)?,
})
}
}
pub fn verify_merkle_proof_directional(
leaf: [u8; 32],
root: [u8; 32],
proof: &[ProofNode],
) -> bool {
if proof.is_empty() {
return false;
}
for node in proof {
if node.side != 'L' && node.side != 'R' {
return false;
}
}
let mut current = leaf;
for node in proof {
match node.side {
'L' => {
let mut combined = Vec::with_capacity(64);
combined.extend_from_slice(&node.hash);
combined.extend_from_slice(¤t);
current = hash256(&combined);
}
'R' => {
let mut combined = Vec::with_capacity(64);
combined.extend_from_slice(¤t);
combined.extend_from_slice(&node.hash);
current = hash256(&combined);
}
_ => return false,
}
}
current == root
}
#[deprecated(
since = "1.0.0",
note = "Use verify_merkle_proof_directional (positional_v1_0_1) instead"
)]
pub fn verify_merkle_proof_legacy_sorted(
leaf: [u8; 32],
root: [u8; 32],
siblings: &[[u8; 32]],
) -> bool {
if siblings.is_empty() {
return false;
}
let mut current = leaf;
for sibling in siblings {
let combined = if current < *sibling {
let mut v = Vec::with_capacity(64);
v.extend_from_slice(¤t);
v.extend_from_slice(sibling);
v
} else {
let mut v = Vec::with_capacity(64);
v.extend_from_slice(sibling);
v.extend_from_slice(¤t);
v
};
current = hash256(&combined);
}
current == root
}