1use crate::{
19 mmr::{
20 storage::{OffchainStorage, RuntimeStorage, Storage},
21 Hasher, Node, NodeOf,
22 },
23 primitives::{
24 mmr_lib, mmr_lib::MMRStoreReadOps, utils::NodesUtils, AncestryProof, Error, FullLeaf,
25 LeafIndex, LeafProof, NodeIndex,
26 },
27 Config, HashOf, HashingOf,
28};
29use alloc::vec::Vec;
30use frame::prelude::*;
31
32pub fn verify_leaves_proof<H, L>(
37 root: H::Output,
38 leaves: Vec<Node<H, L>>,
39 proof: LeafProof<H::Output>,
40) -> Result<bool, Error>
41where
42 H: Hash,
43 L: FullLeaf,
44{
45 let size = NodesUtils::new(proof.leaf_count).size();
46
47 if leaves.len() != proof.leaf_indices.len() {
48 return Err(Error::Verify.log_debug("Proof leaf_indices not same length with leaves"))
49 }
50
51 let leaves_and_position_data = proof
52 .leaf_indices
53 .into_iter()
54 .map(|index| mmr_lib::leaf_index_to_pos(index))
55 .zip(leaves.into_iter())
56 .collect();
57
58 let p = mmr_lib::MerkleProof::<Node<H, L>, Hasher<H, L>>::new(
59 size,
60 proof.items.into_iter().map(Node::Hash).collect(),
61 );
62 p.verify(Node::Hash(root), leaves_and_position_data)
63 .map_err(|e| Error::Verify.log_debug(e))
64}
65
66pub fn is_ancestry_proof_optimal<H>(ancestry_proof: &AncestryProof<H::Output>) -> bool
67where
68 H: frame::traits::Hash,
69{
70 let prev_mmr_size = NodesUtils::new(ancestry_proof.prev_leaf_count).size();
71 let mmr_size = NodesUtils::new(ancestry_proof.leaf_count).size();
72
73 let expected_proof_size =
74 mmr_lib::ancestry_proof::expected_ancestry_proof_size(prev_mmr_size, mmr_size);
75 ancestry_proof.items.len() == expected_proof_size
76}
77
78pub fn verify_ancestry_proof<H, L>(
79 root: H::Output,
80 ancestry_proof: AncestryProof<H::Output>,
81) -> Result<H::Output, Error>
82where
83 H: Hash,
84 L: FullLeaf,
85{
86 let mmr_size = NodesUtils::new(ancestry_proof.leaf_count).size();
87
88 let prev_peaks_proof = mmr_lib::NodeMerkleProof::<Node<H, L>, Hasher<H, L>>::new(
89 mmr_size,
90 ancestry_proof
91 .items
92 .into_iter()
93 .map(|(index, hash)| (index, Node::Hash(hash)))
94 .collect(),
95 );
96
97 let raw_ancestry_proof = mmr_lib::AncestryProof::<Node<H, L>, Hasher<H, L>> {
98 prev_mmr_size: mmr_lib::helper::leaf_index_to_mmr_size(ancestry_proof.prev_leaf_count - 1),
99 prev_peaks: ancestry_proof.prev_peaks.into_iter().map(|hash| Node::Hash(hash)).collect(),
100 prev_peaks_proof,
101 };
102
103 let prev_root = mmr_lib::ancestry_proof::bagging_peaks_hashes::<Node<H, L>, Hasher<H, L>>(
104 raw_ancestry_proof.prev_peaks.clone(),
105 )
106 .map_err(|e| Error::Verify.log_debug(e))?;
107 raw_ancestry_proof
108 .verify_ancestor(Node::Hash(root), prev_root.clone())
109 .map_err(|e| Error::Verify.log_debug(e))?;
110
111 Ok(prev_root.hash())
112}
113
114pub struct Mmr<StorageType, T, I, L>
119where
120 T: Config<I>,
121 I: 'static,
122 L: FullLeaf,
123 Storage<StorageType, T, I, L>:
124 MMRStoreReadOps<NodeOf<T, I, L>> + mmr_lib::MMRStoreWriteOps<NodeOf<T, I, L>>,
125{
126 mmr: mmr_lib::MMR<NodeOf<T, I, L>, Hasher<HashingOf<T, I>, L>, Storage<StorageType, T, I, L>>,
127 leaves: NodeIndex,
128}
129
130impl<StorageType, T, I, L> Mmr<StorageType, T, I, L>
131where
132 T: Config<I>,
133 I: 'static,
134 L: FullLeaf,
135 Storage<StorageType, T, I, L>:
136 MMRStoreReadOps<NodeOf<T, I, L>> + mmr_lib::MMRStoreWriteOps<NodeOf<T, I, L>>,
137{
138 pub fn new(leaves: NodeIndex) -> Self {
140 let size = NodesUtils::new(leaves).size();
141 Self { mmr: mmr_lib::MMR::new(size, Default::default()), leaves }
142 }
143
144 pub fn verify_leaves_proof(
149 &self,
150 leaves: Vec<L>,
151 proof: LeafProof<HashOf<T, I>>,
152 ) -> Result<bool, Error> {
153 let p = mmr_lib::MerkleProof::<NodeOf<T, I, L>, Hasher<HashingOf<T, I>, L>>::new(
154 self.mmr.mmr_size(),
155 proof.items.into_iter().map(Node::Hash).collect(),
156 );
157
158 if leaves.len() != proof.leaf_indices.len() {
159 return Err(Error::Verify.log_debug("Proof leaf_indices not same length with leaves"))
160 }
161
162 let leaves_positions_and_data = proof
163 .leaf_indices
164 .into_iter()
165 .map(|index| mmr_lib::leaf_index_to_pos(index))
166 .zip(leaves.into_iter().map(|leaf| Node::Data(leaf)))
167 .collect();
168 let root = self.mmr.get_root().map_err(|e| Error::GetRoot.log_error(e))?;
169 p.verify(root, leaves_positions_and_data)
170 .map_err(|e| Error::Verify.log_debug(e))
171 }
172
173 #[cfg(any(test, feature = "runtime-benchmarks"))]
175 pub fn size(&self) -> NodeIndex {
176 self.mmr.mmr_size()
177 }
178}
179
180impl<T, I, L> Mmr<RuntimeStorage, T, I, L>
182where
183 T: Config<I>,
184 I: 'static,
185 L: FullLeaf,
186{
187 pub fn push(&mut self, leaf: L) -> Option<NodeIndex> {
191 let position =
192 self.mmr.push(Node::Data(leaf)).map_err(|e| Error::Push.log_error(e)).ok()?;
193
194 self.leaves += 1;
195
196 Some(position)
197 }
198
199 pub fn finalize(mut self) -> Result<(NodeIndex, HashOf<T, I>), Error> {
202 let root = self.mmr.get_root().map_err(|e| Error::GetRoot.log_error(e))?;
203 self.mmr.commit().map_err(|e| Error::Commit.log_error(e))?;
204 Ok((self.leaves, root.hash()))
205 }
206}
207
208impl<T, I, L> Mmr<OffchainStorage, T, I, L>
210where
211 T: Config<I>,
212 I: 'static,
213 L: FullLeaf + codec::Decode,
214{
215 pub fn generate_proof(
220 &self,
221 leaf_indices: Vec<NodeIndex>,
222 ) -> Result<(Vec<L>, LeafProof<HashOf<T, I>>), Error> {
223 let positions = leaf_indices
224 .iter()
225 .map(|index| mmr_lib::leaf_index_to_pos(*index))
226 .collect::<Vec<_>>();
227 let store = <Storage<OffchainStorage, T, I, L>>::default();
228 let leaves = positions
229 .iter()
230 .map(|pos| match store.get_elem(*pos) {
231 Ok(Some(Node::Data(leaf))) => Ok(leaf),
232 e => Err(Error::LeafNotFound.log_debug(e)),
233 })
234 .collect::<Result<Vec<_>, Error>>()?;
235
236 let leaf_count = self.leaves;
237 self.mmr
238 .gen_proof(positions)
239 .map_err(|e| Error::GenerateProof.log_error(e))
240 .map(|p| LeafProof {
241 leaf_indices,
242 leaf_count,
243 items: p.proof_items().iter().map(|x| x.hash()).collect(),
244 })
245 .map(|p| (leaves, p))
246 }
247
248 pub fn generate_ancestry_proof(
249 &self,
250 prev_leaf_count: LeafIndex,
251 ) -> Result<AncestryProof<HashOf<T, I>>, Error> {
252 let prev_mmr_size = NodesUtils::new(prev_leaf_count).size();
253 let raw_ancestry_proof = self
254 .mmr
255 .gen_ancestry_proof(prev_mmr_size)
256 .map_err(|e| Error::GenerateProof.log_error(e))?;
257
258 Ok(AncestryProof {
259 prev_peaks: raw_ancestry_proof.prev_peaks.into_iter().map(|p| p.hash()).collect(),
260 prev_leaf_count,
261 leaf_count: self.leaves,
262 items: raw_ancestry_proof
263 .prev_peaks_proof
264 .proof_items()
265 .iter()
266 .map(|(index, item)| (*index, item.hash()))
267 .collect(),
268 })
269 }
270
271 #[cfg(feature = "runtime-benchmarks")]
276 pub fn generate_mock_ancestry_proof(&self) -> Result<AncestryProof<HashOf<T, I>>, Error> {
277 use crate::ModuleMmr;
278 use alloc::vec;
279 use mmr_lib::helper;
280
281 let mmr: ModuleMmr<OffchainStorage, T, I> = Mmr::new(self.leaves);
282 let store = <Storage<OffchainStorage, T, I, L>>::default();
283
284 let mut prev_peaks = vec![];
285 for peak_pos in helper::get_peaks(mmr.size()) {
286 let peak = store
287 .get_elem(peak_pos)
288 .map_err(|_| Error::GenerateProof)?
289 .ok_or(Error::GenerateProof)?
290 .hash();
291 prev_peaks.push(peak);
292 }
293
294 let mut proof_items = vec![];
295 for leaf_idx in 0..self.leaves {
296 let leaf_pos = NodesUtils::leaf_index_to_leaf_node_index(leaf_idx);
297 let leaf = store
298 .get_elem(leaf_pos)
299 .map_err(|_| Error::GenerateProof)?
300 .ok_or(Error::GenerateProof)?
301 .hash();
302 proof_items.push((leaf_pos, leaf));
303 }
304
305 Ok(AncestryProof {
306 prev_peaks,
307 prev_leaf_count: self.leaves,
308 leaf_count: self.leaves,
309 items: proof_items,
310 })
311 }
312}