1#![cfg_attr(not(feature = "std"), no_std)]
21#![warn(missing_docs)]
22
23extern crate alloc;
24
25pub use mmr_lib;
26
27#[cfg(not(feature = "std"))]
28use alloc::vec::Vec;
29use codec::{Decode, DecodeWithMemTracking, Encode};
30use core::fmt;
31use scale_info::TypeInfo;
32use sp_runtime::traits;
33
34pub mod utils;
35
36pub const INDEXING_PREFIX: &'static [u8] = b"mmr";
38
39pub type NodeIndex = u64;
41
42pub type LeafIndex = u64;
48
49pub trait LeafDataProvider {
51 type LeafData: FullLeaf + codec::Decode;
53
54 fn leaf_data() -> Self::LeafData;
60}
61
62impl LeafDataProvider for () {
63 type LeafData = ();
64
65 fn leaf_data() -> Self::LeafData {
66 ()
67 }
68}
69
70pub trait OnNewRoot<Hash> {
72 fn on_new_root(root: &Hash);
74}
75
76impl<Hash> OnNewRoot<Hash> for () {
78 fn on_new_root(_root: &Hash) {}
79}
80
81pub trait FullLeaf: Clone + PartialEq + fmt::Debug {
83 fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F, compact: bool) -> R;
87}
88
89impl<T: codec::Encode + codec::Decode + Clone + PartialEq + fmt::Debug> FullLeaf for T {
90 fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F, _compact: bool) -> R {
91 codec::Encode::using_encoded(self, f)
92 }
93}
94
95#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
107#[derive(Debug, Clone, PartialEq)]
108pub struct OpaqueLeaf(
109 #[cfg_attr(feature = "serde", serde(with = "sp_core::bytes"))]
113 pub Vec<u8>,
114);
115
116impl OpaqueLeaf {
117 pub fn from_leaf<T: FullLeaf>(leaf: &T) -> Self {
119 let encoded_leaf = leaf.using_encoded(|d| d.to_vec(), true);
120 OpaqueLeaf::from_encoded_leaf(encoded_leaf)
121 }
122
123 pub fn from_encoded_leaf(encoded_leaf: Vec<u8>) -> Self {
125 OpaqueLeaf(encoded_leaf)
126 }
127
128 pub fn try_decode<T: codec::Decode>(&self) -> Option<T> {
130 codec::Decode::decode(&mut &*self.0).ok()
131 }
132}
133
134impl FullLeaf for OpaqueLeaf {
135 fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F, _compact: bool) -> R {
136 f(&self.0)
137 }
138}
139
140#[derive(codec::Encode, codec::Decode, Debug, Clone, PartialEq, Eq, TypeInfo)]
148pub struct EncodableOpaqueLeaf(pub Vec<u8>);
149
150impl EncodableOpaqueLeaf {
151 pub fn from_leaf<T: FullLeaf>(leaf: &T) -> Self {
153 let opaque = OpaqueLeaf::from_leaf(leaf);
154 Self::from_opaque_leaf(opaque)
155 }
156
157 pub fn from_opaque_leaf(opaque: OpaqueLeaf) -> Self {
159 Self(opaque.0)
160 }
161
162 pub fn into_opaque_leaf(self) -> OpaqueLeaf {
164 OpaqueLeaf::from_encoded_leaf(self.0)
166 }
167}
168
169#[derive(Debug, Clone, PartialEq)]
179pub enum DataOrHash<H: traits::Hash, L> {
180 Data(L),
182 Hash(H::Output),
184}
185
186impl<H: traits::Hash, L> From<L> for DataOrHash<H, L> {
187 fn from(l: L) -> Self {
188 Self::Data(l)
189 }
190}
191
192mod encoding {
193 use super::*;
194
195 #[derive(codec::Encode, codec::Decode)]
197 enum Either<A, B> {
198 Left(A),
199 Right(B),
200 }
201
202 impl<H: traits::Hash, L: FullLeaf> codec::Encode for DataOrHash<H, L> {
203 fn encode_to<T: codec::Output + ?Sized>(&self, dest: &mut T) {
204 match self {
205 Self::Data(l) => l.using_encoded(
206 |data| Either::<&[u8], &H::Output>::Left(data).encode_to(dest),
207 false,
208 ),
209 Self::Hash(h) => Either::<&[u8], &H::Output>::Right(h).encode_to(dest),
210 }
211 }
212 }
213
214 impl<H: traits::Hash, L: FullLeaf + codec::Decode> codec::Decode for DataOrHash<H, L> {
215 fn decode<I: codec::Input>(value: &mut I) -> Result<Self, codec::Error> {
216 let decoded: Either<Vec<u8>, H::Output> = Either::decode(value)?;
217 Ok(match decoded {
218 Either::Left(l) => DataOrHash::Data(L::decode(&mut &*l)?),
219 Either::Right(r) => DataOrHash::Hash(r),
220 })
221 }
222 }
223}
224
225impl<H: traits::Hash, L: FullLeaf> DataOrHash<H, L> {
226 pub fn hash(&self) -> H::Output {
231 match *self {
232 Self::Data(ref leaf) => leaf.using_encoded(<H as traits::Hash>::hash, true),
233 Self::Hash(ref hash) => *hash,
234 }
235 }
236}
237
238#[derive(Debug, Clone, PartialEq)]
250pub struct Compact<H, T> {
251 pub tuple: T,
253 _hash: core::marker::PhantomData<H>,
254}
255
256impl<H, T> core::ops::Deref for Compact<H, T> {
257 type Target = T;
258
259 fn deref(&self) -> &Self::Target {
260 &self.tuple
261 }
262}
263
264impl<H, T> Compact<H, T> {
265 pub fn new(tuple: T) -> Self {
267 Self { tuple, _hash: Default::default() }
268 }
269}
270
271impl<H, T: codec::Decode> codec::Decode for Compact<H, T> {
272 fn decode<I: codec::Input>(value: &mut I) -> Result<Self, codec::Error> {
273 T::decode(value).map(Compact::new)
274 }
275}
276
277macro_rules! impl_leaf_data_for_tuple {
278 ( $( $name:ident : $id:tt ),+ ) => {
279 impl<H, $( $name ),+> FullLeaf for Compact<H, ( $( DataOrHash<H, $name>, )+ )> where
281 H: traits::Hash,
282 $( $name: FullLeaf ),+
283 {
284 fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F, compact: bool) -> R {
285 if compact {
286 codec::Encode::using_encoded(&(
287 $( DataOrHash::<H, $name>::Hash(self.tuple.$id.hash()), )+
288 ), f)
289 } else {
290 codec::Encode::using_encoded(&self.tuple, f)
291 }
292 }
293 }
294
295 impl<H, $( $name ),+> LeafDataProvider for Compact<H, ( $( $name, )+ )> where
299 H: traits::Hash,
300 $( $name: LeafDataProvider ),+
301 {
302 type LeafData = Compact<
303 H,
304 ( $( DataOrHash<H, $name::LeafData>, )+ ),
305 >;
306
307 fn leaf_data() -> Self::LeafData {
308 let tuple = (
309 $( DataOrHash::Data($name::leaf_data()), )+
310 );
311 Compact::new(tuple)
312 }
313 }
314
315 impl<$( $name ),+> LeafDataProvider for ( $( $name, )+ ) where
319 ( $( $name::LeafData, )+ ): FullLeaf,
320 $( $name: LeafDataProvider ),+
321 {
322 type LeafData = ( $( $name::LeafData, )+ );
323
324 fn leaf_data() -> Self::LeafData {
325 (
326 $( $name::leaf_data(), )+
327 )
328 }
329 }
330 }
331}
332
333#[cfg(test)]
335impl<H, A, B> Compact<H, (DataOrHash<H, A>, DataOrHash<H, B>)>
336where
337 H: traits::Hash,
338 A: FullLeaf,
339 B: FullLeaf,
340{
341 pub fn hash(&self) -> H::Output {
343 self.using_encoded(<H as traits::Hash>::hash, true)
344 }
345}
346
347impl_leaf_data_for_tuple!(A:0);
348impl_leaf_data_for_tuple!(A:0, B:1);
349impl_leaf_data_for_tuple!(A:0, B:1, C:2);
350impl_leaf_data_for_tuple!(A:0, B:1, C:2, D:3);
351impl_leaf_data_for_tuple!(A:0, B:1, C:2, D:3, E:4);
352
353#[derive(codec::Encode, codec::Decode, Debug, Clone, PartialEq, Eq, TypeInfo)]
355pub struct LeafProof<Hash> {
356 pub leaf_indices: Vec<LeafIndex>,
358 pub leaf_count: NodeIndex,
360 pub items: Vec<Hash>,
362}
363
364#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
366#[derive(Encode, Decode, DecodeWithMemTracking, Debug, Clone, PartialEq, Eq, TypeInfo)]
367pub struct AncestryProof<Hash> {
368 pub prev_peaks: Vec<Hash>,
370 pub prev_leaf_count: u64,
372 pub leaf_count: NodeIndex,
374 pub items: Vec<(u64, Hash)>,
377}
378
379#[cfg_attr(feature = "std", derive(thiserror::Error))]
381#[derive(Debug, codec::Encode, codec::Decode, PartialEq, Eq, TypeInfo)]
382pub enum Error {
383 #[cfg_attr(feature = "std", error("Error performing numeric op"))]
385 InvalidNumericOp,
386 #[cfg_attr(feature = "std", error("Error pushing new node"))]
388 Push,
389 #[cfg_attr(feature = "std", error("Error getting new root"))]
391 GetRoot,
392 #[cfg_attr(feature = "std", error("Error committing changes"))]
394 Commit,
395 #[cfg_attr(feature = "std", error("Error generating proof"))]
397 GenerateProof,
398 #[cfg_attr(feature = "std", error("Invalid proof"))]
400 Verify,
401 #[cfg_attr(feature = "std", error("Leaf was not found"))]
403 LeafNotFound,
404 #[cfg_attr(feature = "std", error("MMR pallet not included in runtime"))]
406 PalletNotIncluded,
407 #[cfg_attr(feature = "std", error("Requested leaf index invalid"))]
409 InvalidLeafIndex,
410 #[cfg_attr(feature = "std", error("Provided best known block number invalid"))]
412 InvalidBestKnownBlock,
413}
414
415impl Error {
416 #![allow(unused_variables)]
417 pub fn log_error(self, e: impl fmt::Debug) -> Self {
419 log::error!(
420 target: "runtime::mmr",
421 "[{:?}] MMR error: {:?}",
422 self,
423 e,
424 );
425 self
426 }
427
428 pub fn log_debug(self, e: impl fmt::Debug) -> Self {
430 log::debug!(
431 target: "runtime::mmr",
432 "[{:?}] MMR error: {:?}",
433 self,
434 e,
435 );
436 self
437 }
438}
439
440sp_api::decl_runtime_apis! {
441 #[api_version(3)]
443 pub trait MmrApi<Hash: codec::Codec, BlockNumber: codec::Codec> {
444 fn mmr_root() -> Result<Hash, Error>;
446
447 fn mmr_leaf_count() -> Result<LeafIndex, Error>;
449
450 fn generate_proof(
453 block_numbers: Vec<BlockNumber>,
454 best_known_block_number: Option<BlockNumber>
455 ) -> Result<(Vec<EncodableOpaqueLeaf>, LeafProof<Hash>), Error>;
456
457 fn generate_ancestry_proof(
460 prev_block_number: BlockNumber,
461 best_known_block_number: Option<BlockNumber>,
462 ) -> Result<AncestryProof<Hash>, Error>;
463
464 fn verify_proof(leaves: Vec<EncodableOpaqueLeaf>, proof: LeafProof<Hash>) -> Result<(), Error>;
470
471 fn verify_proof_stateless(root: Hash, leaves: Vec<EncodableOpaqueLeaf>, proof: LeafProof<Hash>)
479 -> Result<(), Error>;
480 }
481}
482
483#[cfg(test)]
484mod tests {
485 use super::*;
486
487 use codec::Decode;
488 use sp_core::H256;
489 use sp_runtime::traits::Keccak256;
490
491 pub(crate) fn hex(s: &str) -> H256 {
492 s.parse().unwrap()
493 }
494
495 type Test = DataOrHash<Keccak256, String>;
496 type TestCompact = Compact<Keccak256, (Test, Test)>;
497 type TestProof = LeafProof<<Keccak256 as traits::Hash>::Output>;
498
499 #[test]
500 fn should_encode_decode_proof() {
501 let proof: TestProof = LeafProof {
503 leaf_indices: vec![5],
504 leaf_count: 10,
505 items: vec![
506 hex("c3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd"),
507 hex("d3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd"),
508 hex("e3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd"),
509 ],
510 };
511
512 let encoded = codec::Encode::encode(&proof);
514 let decoded = TestProof::decode(&mut &*encoded);
515
516 assert_eq!(decoded, Ok(proof));
518 }
519
520 #[test]
521 fn should_encode_decode_correctly_if_no_compact() {
522 let cases = vec![
524 Test::Data("Hello World!".into()),
525 Test::Hash(hex("c3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd")),
526 Test::Data("".into()),
527 Test::Data("3e48d6bcd417fb22e044747242451e2c0f3e602d1bcad2767c34808621956417".into()),
528 ];
529
530 let encoded = cases.iter().map(codec::Encode::encode).collect::<Vec<_>>();
532
533 let decoded = encoded.iter().map(|x| Test::decode(&mut &**x)).collect::<Vec<_>>();
534
535 assert_eq!(
537 decoded,
538 cases.into_iter().map(Result::<_, codec::Error>::Ok).collect::<Vec<_>>()
539 );
540 assert_eq!(
542 &encoded[0],
543 &array_bytes::hex2bytes_unchecked("00343048656c6c6f20576f726c6421")
544 );
545 assert_eq!(
546 encoded[1].as_slice(),
547 array_bytes::hex2bytes_unchecked(
548 "01c3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd"
549 )
550 .as_slice()
551 );
552 }
553
554 #[test]
555 fn should_return_the_hash_correctly() {
556 let a = Test::Data("Hello World!".into());
558 let b = Test::Hash(hex("c3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd"));
559
560 let a = a.hash();
562 let b = b.hash();
563
564 assert_eq!(a, hex("a9c321be8c24ba4dc2bd73f5300bde67dc57228ab8b68b607bb4c39c5374fac9"));
566 assert_eq!(b, hex("c3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd"));
567 }
568
569 #[test]
570 fn compact_should_work() {
571 let a = Test::Data("Hello World!".into());
573 let b = Test::Data("".into());
574
575 let c: TestCompact = Compact::new((a.clone(), b.clone()));
577 let d: TestCompact = Compact::new((Test::Hash(a.hash()), Test::Hash(b.hash())));
578
579 assert_eq!(c.hash(), d.hash());
581 }
582
583 #[test]
584 fn compact_should_encode_decode_correctly() {
585 let a = Test::Data("Hello World!".into());
587 let b = Test::Data("".into());
588
589 let c: TestCompact = Compact::new((a.clone(), b.clone()));
590 let d: TestCompact = Compact::new((Test::Hash(a.hash()), Test::Hash(b.hash())));
591 let cases = vec![c, d.clone()];
592
593 let encoded_compact =
595 cases.iter().map(|c| c.using_encoded(|x| x.to_vec(), true)).collect::<Vec<_>>();
596
597 let encoded =
598 cases.iter().map(|c| c.using_encoded(|x| x.to_vec(), false)).collect::<Vec<_>>();
599
600 let decoded_compact = encoded_compact
601 .iter()
602 .map(|x| TestCompact::decode(&mut &**x))
603 .collect::<Vec<_>>();
604
605 let decoded = encoded.iter().map(|x| TestCompact::decode(&mut &**x)).collect::<Vec<_>>();
606
607 assert_eq!(
609 decoded,
610 cases.into_iter().map(Result::<_, codec::Error>::Ok).collect::<Vec<_>>()
611 );
612
613 assert_eq!(decoded_compact, vec![Ok(d.clone()), Ok(d.clone())]);
614 }
615
616 #[test]
617 fn opaque_leaves_should_be_full_leaf_compatible() {
618 let a = Test::Data("Hello World!".into());
620 let b = Test::Data("".into());
621
622 let c: TestCompact = Compact::new((a.clone(), b.clone()));
623 let d: TestCompact = Compact::new((Test::Hash(a.hash()), Test::Hash(b.hash())));
624 let cases = vec![c, d.clone()];
625
626 let encoded_compact = cases
627 .iter()
628 .map(|c| c.using_encoded(|x| x.to_vec(), true))
629 .map(OpaqueLeaf::from_encoded_leaf)
630 .collect::<Vec<_>>();
631
632 let opaque = cases.iter().map(OpaqueLeaf::from_leaf).collect::<Vec<_>>();
633
634 assert_eq!(encoded_compact, opaque);
636 }
637
638 #[test]
639 fn encode_opaque_leaf_should_be_scale_compatible() {
640 use codec::Encode;
641
642 let a = Test::Data("Hello World!".into());
644 let case1 = EncodableOpaqueLeaf::from_leaf(&a);
645 let case2 = EncodableOpaqueLeaf::from_opaque_leaf(OpaqueLeaf(a.encode()));
646 let case3 = a.encode().encode();
647
648 let encoded = vec![&case1, &case2].into_iter().map(|x| x.encode()).collect::<Vec<_>>();
650 let decoded = vec![&*encoded[0], &*encoded[1], &*case3]
651 .into_iter()
652 .map(|x| EncodableOpaqueLeaf::decode(&mut &*x))
653 .collect::<Vec<_>>();
654
655 assert_eq!(case1, case2);
657 assert_eq!(encoded[0], encoded[1]);
658 assert_eq!(encoded[0], case3);
660
661 assert_eq!(decoded[0], decoded[1]);
662 assert_eq!(decoded[1], decoded[2]);
663 assert_eq!(decoded[0], Ok(case2));
664 assert_eq!(decoded[1], Ok(case1));
665 }
666}