in akd_client/src/verify.rs [57:101]
fn verify_nonmembership(
root_hash: Digest,
proof: &NonMembershipProof,
) -> Result<bool, VerificationError> {
let mut verified = true;
let mut lcp_hash = hash(&EMPTY_VALUE);
let mut lcp_real = proof.longest_prefix_children[0].label;
for i in 0..ARITY {
let child_hash = merge(&[
proof.longest_prefix_children[i].hash,
proof.longest_prefix_children[i].label.hash(),
]);
lcp_hash = merge(&[lcp_hash, child_hash]);
lcp_real = lcp_real.get_longest_common_prefix(proof.longest_prefix_children[i].label);
}
if lcp_real == EMPTY_LABEL {
lcp_real = NodeLabel {
val: [0u8; 32],
len: 0,
};
}
// lcp_hash = H::merge(&[lcp_hash, hash_label::<H>(proof.longest_prefix)]);
verified = verified && (lcp_hash == proof.longest_prefix_membership_proof.hash_val);
if !verified {
return Err(verify_error!(
LookupProof,
bool,
"lcp_hash != longest_prefix_hash".to_string()
));
}
verify_membership(root_hash, &proof.longest_prefix_membership_proof)?;
// The audit must have checked that this node is indeed the lcp of its children.
// So we can just check that one of the children's lcp is = the proof.longest_prefix
verified = verified && (proof.longest_prefix == lcp_real);
if !verified {
return Err(verify_error!(
LookupProof,
bool,
"longest_prefix != lcp".to_string()
));
}
Ok(verified)
}