use alloc::vec::Vec;
use borsh::{BorshDeserialize, BorshSerialize};
use risc0_core::field::baby_bear::BabyBear;
use risc0_zkp::core::{digest::Digest, hash::HashFn};
use serde::{Deserialize, Serialize};
use crate::zk_precompiles::risc0::R0Error;
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, BorshSerialize, BorshDeserialize)]
pub struct MerkleProof {
pub index: u32,
pub digests: Vec<Digest>,
}
impl MerkleProof {
pub fn verify(&self, leaf: &Digest, root: &Digest, hashfn: &dyn HashFn<BabyBear>) -> Result<(), R0Error> {
if self.root(leaf, hashfn)? == *root {
return Ok(());
}
Err(R0Error::Merkle)
}
pub fn root(&self, leaf: &Digest, hashfn: &dyn HashFn<BabyBear>) -> Result<Digest, R0Error> {
if !hashfn.is_digest_valid(leaf) {
return Err(R0Error::Merkle);
}
let mut cur = *leaf;
let mut cur_index = self.index;
for sibling in &self.digests {
if !hashfn.is_digest_valid(sibling) {
return Err(R0Error::Merkle);
}
cur = if cur_index & 1 == 0 { *hashfn.hash_pair(&cur, sibling) } else { *hashfn.hash_pair(sibling, &cur) };
cur_index >>= 1;
}
Ok(cur)
}
}