ibc_relayer_types/core/ics23_commitment/
merkle.rs1use tendermint::merkle::proof::ProofOps as TendermintProof;
2
3use ibc_proto::ibc::core::commitment::v1::MerklePath;
4use ibc_proto::ibc::core::commitment::v1::MerkleProof as RawMerkleProof;
5use ibc_proto::ibc::core::commitment::v1::MerkleRoot;
6use ics23::commitment_proof::Proof;
7use ics23::{
8 calculate_existence_root, verify_membership, verify_non_membership, CommitmentProof,
9 NonExistenceProof,
10};
11
12use crate::core::ics23_commitment::commitment::{CommitmentPrefix, CommitmentRoot};
13use crate::core::ics23_commitment::error::Error;
14use crate::core::ics23_commitment::specs::ProofSpecs;
15
16pub fn apply_prefix(prefix: &CommitmentPrefix, mut path: Vec<String>) -> MerklePath {
17 let mut key_path: Vec<String> = vec![format!("{prefix:?}")];
18 key_path.append(&mut path);
19 MerklePath { key_path }
20}
21
22impl From<CommitmentRoot> for MerkleRoot {
23 fn from(root: CommitmentRoot) -> Self {
24 Self {
25 hash: root.into_vec(),
26 }
27 }
28}
29
30#[derive(Clone, Debug, PartialEq)]
31pub struct MerkleProof {
32 pub proofs: Vec<CommitmentProof>,
33}
34
35impl From<RawMerkleProof> for MerkleProof {
37 fn from(proof: RawMerkleProof) -> Self {
38 Self {
39 proofs: proof.proofs,
40 }
41 }
42}
43
44impl From<MerkleProof> for RawMerkleProof {
45 fn from(proof: MerkleProof) -> Self {
46 Self {
47 proofs: proof.proofs,
48 }
49 }
50}
51
52impl MerkleProof {
53 pub fn verify_membership(
54 &self,
55 specs: &ProofSpecs,
56 root: MerkleRoot,
57 keys: MerklePath,
58 value: Vec<u8>,
59 start_index: usize,
60 ) -> Result<(), Error> {
61 if self.proofs.is_empty() {
63 return Err(Error::empty_merkle_proof());
64 }
65 if root.hash.is_empty() {
66 return Err(Error::empty_merkle_root());
67 }
68 let num = self.proofs.len();
69 let ics23_specs = Vec::<ics23::ProofSpec>::from(specs.clone());
70 if ics23_specs.len() != num {
71 return Err(Error::number_of_specs_mismatch());
72 }
73 if keys.key_path.len() != num {
74 return Err(Error::number_of_keys_mismatch());
75 }
76 if value.is_empty() {
77 return Err(Error::empty_verified_value());
78 }
79
80 let mut subroot = value.clone();
81 let mut value = value;
82 for ((proof, spec), key) in self
84 .proofs
85 .iter()
86 .zip(ics23_specs.iter())
87 .zip(keys.key_path.iter().rev())
88 .skip(start_index)
89 {
90 match &proof.proof {
91 Some(Proof::Exist(existence_proof)) => {
92 subroot =
93 calculate_existence_root::<ics23::HostFunctionsManager>(existence_proof)
94 .map_err(|_| Error::invalid_merkle_proof())?;
95
96 if !verify_membership::<ics23::HostFunctionsManager>(
97 proof,
98 spec,
99 &subroot,
100 key.as_bytes(),
101 &value,
102 ) {
103 return Err(Error::verification_failure());
104 }
105 value.clone_from(&subroot);
106 }
107 _ => return Err(Error::invalid_merkle_proof()),
108 }
109 }
110
111 if root.hash != subroot {
112 return Err(Error::verification_failure());
113 }
114
115 Ok(())
116 }
117
118 pub fn verify_non_membership(
119 &self,
120 specs: &ProofSpecs,
121 root: MerkleRoot,
122 keys: MerklePath,
123 ) -> Result<(), Error> {
124 if self.proofs.is_empty() {
126 return Err(Error::empty_merkle_proof());
127 }
128 if root.hash.is_empty() {
129 return Err(Error::empty_merkle_root());
130 }
131 let num = self.proofs.len();
132 let ics23_specs = Vec::<ics23::ProofSpec>::from(specs.clone());
133 if ics23_specs.len() != num {
134 return Err(Error::number_of_specs_mismatch());
135 }
136 if keys.key_path.len() != num {
137 return Err(Error::number_of_keys_mismatch());
138 }
139
140 let proof = self
142 .proofs
143 .first()
144 .ok_or_else(Error::invalid_merkle_proof)?;
145 let spec = ics23_specs
146 .first()
147 .ok_or_else(Error::invalid_merkle_proof)?;
148 let key = keys
150 .key_path
151 .get(num - 1)
152 .ok_or_else(Error::invalid_merkle_proof)?;
153 match &proof.proof {
154 Some(Proof::Nonexist(non_existence_proof)) => {
155 let subroot = calculate_non_existence_root(non_existence_proof)?;
156
157 if !verify_non_membership::<ics23::HostFunctionsManager>(
158 proof,
159 spec,
160 &subroot,
161 key.as_bytes(),
162 ) {
163 return Err(Error::verification_failure());
164 }
165
166 self.verify_membership(specs, root, keys, subroot, 1)
168 }
169 _ => Err(Error::invalid_merkle_proof()),
170 }
171 }
172}
173
174fn calculate_non_existence_root(proof: &NonExistenceProof) -> Result<Vec<u8>, Error> {
176 if let Some(left) = &proof.left {
177 calculate_existence_root::<ics23::HostFunctionsManager>(left)
178 .map_err(|_| Error::invalid_merkle_proof())
179 } else if let Some(right) = &proof.right {
180 calculate_existence_root::<ics23::HostFunctionsManager>(right)
181 .map_err(|_| Error::invalid_merkle_proof())
182 } else {
183 Err(Error::invalid_merkle_proof())
184 }
185}
186
187pub fn convert_tm_to_ics_merkle_proof(tm_proof: &TendermintProof) -> Result<MerkleProof, Error> {
240 let mut proofs = Vec::new();
241
242 for op in &tm_proof.ops {
243 let mut parsed = CommitmentProof { proof: None };
244
245 prost::Message::merge(&mut parsed, op.data.as_slice())
246 .map_err(Error::commitment_proof_decoding_failed)?;
247
248 proofs.push(parsed);
249 }
250
251 Ok(MerkleProof::from(RawMerkleProof { proofs }))
252}