use core::fmt::Debug; use core::marker::PhantomData; use ibc_relayer_types::core::ics23_commitment::error::Error as ProofError; use ics23::{ calculate_existence_root, commitment_proof::Proof, verify_membership, CommitmentProof, ProofSpec, }; use tendermint::merkle::proof::ProofOps; use tendermint_rpc::endpoint::abci_query::AbciQuery; // Copied from hermes pub fn convert_tm_to_ics_merkle_proof( tm_proof: &ProofOps, ) -> Result, ProofError> { let mut proofs = Vec::new(); for op in &tm_proof.ops { let mut parsed = CommitmentProof { proof: None }; prost::Message::merge(&mut parsed, op.data.as_slice()) .map_err(ProofError::commitment_proof_decoding_failed)?; proofs.push(parsed); } Ok(proofs) } trait Verifier { type Proof; type Root: Eq; type Key; type Value; type Error; fn verify( &self, proof: &Self::Proof, key: &Self::Key, value: &Self::Value, ) -> Result; fn verify_against_root( &self, proof: &Self::Proof, key: &Self::Key, value: &Self::Value, root: &Self::Root, ) -> Result { let found_root = self.verify(proof, key, value)?; Ok(root == &found_root) } } #[derive(Clone, Debug)] struct Ics23MembershipVerifier { spec: ProofSpec, _phantom: PhantomData<(K, V)>, } impl Ics23MembershipVerifier { fn new(spec: ProofSpec) -> Self { Self { spec, _phantom: Default::default(), } } } impl Verifier for Ics23MembershipVerifier where K: AsRef<[u8]>, V: AsRef<[u8]>, { type Proof = CommitmentProof; type Root = Vec; type Key = K; type Value = V; type Error = ProofError; fn verify( &self, commitment_proof: &Self::Proof, key: &Self::Key, value: &Self::Value, ) -> Result { if value.as_ref().is_empty() { return Err(ProofError::empty_verified_value()); } let Some(Proof::Exist(existence_proof)) = &commitment_proof.proof else { return Err(ProofError::invalid_merkle_proof()); }; let root = calculate_existence_root::(existence_proof) .map_err(|_| ProofError::invalid_merkle_proof())?; if !verify_membership::( commitment_proof, &self.spec, &root, key.as_ref(), value.as_ref(), ) { return Err(ProofError::verification_failure()); } Ok(root) } } #[derive(Clone, Debug)] struct MultiVerifier { verifiers: [V; N], } impl MultiVerifier { fn new(verifiers: [V; N]) -> Self { assert!(N > 0, "cannot create empty multi-verifiers"); Self { verifiers } } } impl Verifier for MultiVerifier where V: Verifier, V::Value: Clone, V::Root: Into + Clone, { type Proof = [V::Proof; N]; type Root = V::Root; type Key = [V::Key; N]; type Value = V::Value; type Error = V::Error; fn verify( &self, proofs: &Self::Proof, keys: &Self::Key, value: &Self::Value, ) -> Result { let mut root = None; let mut value = value.clone(); for (idx, verifier) in self.verifiers.iter().enumerate() { let proof = &proofs[idx]; let key = &keys[N - idx - 1]; let sub_root = verifier.verify(proof, key, &value)?; value = sub_root.clone().into(); root = Some(sub_root); } Ok(root.expect("MultiVerifier cannot be instantiated with 0 verifiers")) } } #[derive(Clone, Debug)] pub struct CwVerifier(MultiVerifier, Vec>, 2>); impl CwVerifier { pub fn new() -> Self { let mv = MultiVerifier::new([ Ics23MembershipVerifier::new(ics23::iavl_spec()), Ics23MembershipVerifier::new(ics23::tendermint_spec()), ]); Self(mv) } pub fn verify( &self, proofs: &[CommitmentProof; 2], root: &Vec, keys: &[Vec; 2], value: &Vec, ) -> Result<(), ProofError> { if root.is_empty() { return Err(ProofError::empty_merkle_root()); } let verified = self.0.verify_against_root(proofs, keys, value, root)?; if !verified { return Err(ProofError::verification_failure()); } Ok(()) } } pub trait CwProof { type Key; type Value; type Proof; fn verify(self, root: Vec) -> Result<(), ProofError>; } trait IntoKeys { fn into_keys(self) -> Vec>; } struct PrefixedKey { key: K, prefix: PhantomData

, } impl PrefixedKey { fn new(key: K) -> Self { Self { key, prefix: PhantomData, } } } impl IntoKeys for PrefixedKey where K: Into>, P: ConstPrefix, { fn into_keys(self) -> Vec> { vec![P::PREFIX.to_string().into_bytes(), self.key.into()] } } struct PrefixWasm; trait ConstPrefix { const PREFIX: &'static str; } impl ConstPrefix for PrefixWasm { const PREFIX: &'static str = "wasm"; } impl IntoKeys for K where K: Into>, { fn into_keys(self) -> Vec> { vec![self.into()] } } pub struct QueryProof { proof: ProofOps, key: PrefixedKey, value: V, } pub type RawQueryProof = QueryProof, Vec>; #[derive(Clone, Debug)] pub struct ErrorWithoutProof; impl TryFrom for RawQueryProof { type Error = ErrorWithoutProof; fn try_from(query: AbciQuery) -> Result { let AbciQuery { key, value, proof, .. } = query; let Some(proof) = proof else { return Err(ErrorWithoutProof); }; Ok(Self { proof, key: PrefixedKey::new(key), value, }) } } impl CwProof for QueryProof where K: Into>, V: Into>, { type Key = K; type Value = V; type Proof = ProofOps; fn verify(self, root: Vec) -> Result<(), ProofError> { fn as_array_2(v: Vec) -> Result<[T; 2], ProofError> { let boxed_slice = v.into_boxed_slice(); let boxed_array: Box<[T; 2]> = boxed_slice.try_into().expect("todo"); Ok(*boxed_array) } let Self { proof, key, value } = self; let proofs = convert_tm_to_ics_merkle_proof(&proof)?; let cw_verifier = CwVerifier::new(); cw_verifier.verify( &as_array_2(proofs)?, &root, &as_array_2(key.into_keys())?, &value.into(), )?; Ok(()) } }