mithril_stm/circuits/halo2/
adapters.rs1use digest::Digest;
4use thiserror::Error;
5
6use crate::circuits::halo2::types::{MerklePath as Halo2MerklePath, Position};
7use crate::membership_commitment::MerklePath as StmMerklePath;
8use crate::signature_scheme::BaseFieldElement;
9
10#[derive(Debug, Error)]
12pub enum MerklePathAdapterError {
13 #[error("invalid merkle digest length")]
14 InvalidDigestLength,
15 #[error("non-canonical merkle digest")]
16 NonCanonicalDigest,
17}
18
19impl<D: Digest> TryFrom<&StmMerklePath<D>> for Halo2MerklePath {
20 type Error = MerklePathAdapterError;
21
22 fn try_from(stm_path: &StmMerklePath<D>) -> Result<Self, Self::Error> {
23 let mut siblings = Vec::with_capacity(stm_path.values.len());
24
25 for (i, value) in stm_path.values.iter().enumerate() {
26 let bytes: [u8; 32] = value
27 .as_slice()
28 .try_into()
29 .map_err(|_| MerklePathAdapterError::InvalidDigestLength)?;
30 let node = BaseFieldElement::from_bytes(&bytes)
31 .ok()
32 .map(|base| base.into())
33 .ok_or(MerklePathAdapterError::NonCanonicalDigest)?;
34 let bit = (stm_path.index >> i) & 1;
35 let position = if bit == 0 {
39 Position::Right
40 } else {
41 Position::Left
42 };
43 siblings.push((position, node));
44 }
45
46 Ok(Halo2MerklePath::new(siblings))
47 }
48}