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_debug_derive::RuntimeDebug;
33use sp_runtime::traits;
34
35pub mod utils;
36
37pub const INDEXING_PREFIX: &'static [u8] = b"mmr";
39
40pub type NodeIndex = u64;
42
43pub type LeafIndex = u64;
49
50pub trait LeafDataProvider {
52 type LeafData: FullLeaf + codec::Decode;
54
55 fn leaf_data() -> Self::LeafData;
61}
62
63impl LeafDataProvider for () {
64 type LeafData = ();
65
66 fn leaf_data() -> Self::LeafData {
67 ()
68 }
69}
70
71pub trait OnNewRoot<Hash> {
73 fn on_new_root(root: &Hash);
75}
76
77impl<Hash> OnNewRoot<Hash> for () {
79 fn on_new_root(_root: &Hash) {}
80}
81
82pub trait FullLeaf: Clone + PartialEq + fmt::Debug {
84 fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F, compact: bool) -> R;
88}
89
90impl<T: codec::Encode + codec::Decode + Clone + PartialEq + fmt::Debug> FullLeaf for T {
91 fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F, _compact: bool) -> R {
92 codec::Encode::using_encoded(self, f)
93 }
94}
95
96#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
108#[derive(RuntimeDebug, Clone, PartialEq)]
109pub struct OpaqueLeaf(
110 #[cfg_attr(feature = "serde", serde(with = "sp_core::bytes"))]
114 pub Vec<u8>,
115);
116
117impl OpaqueLeaf {
118 pub fn from_leaf<T: FullLeaf>(leaf: &T) -> Self {
120 let encoded_leaf = leaf.using_encoded(|d| d.to_vec(), true);
121 OpaqueLeaf::from_encoded_leaf(encoded_leaf)
122 }
123
124 pub fn from_encoded_leaf(encoded_leaf: Vec<u8>) -> Self {
126 OpaqueLeaf(encoded_leaf)
127 }
128
129 pub fn try_decode<T: codec::Decode>(&self) -> Option<T> {
131 codec::Decode::decode(&mut &*self.0).ok()
132 }
133}
134
135impl FullLeaf for OpaqueLeaf {
136 fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F, _compact: bool) -> R {
137 f(&self.0)
138 }
139}
140
141#[derive(codec::Encode, codec::Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)]
149pub struct EncodableOpaqueLeaf(pub Vec<u8>);
150
151impl EncodableOpaqueLeaf {
152 pub fn from_leaf<T: FullLeaf>(leaf: &T) -> Self {
154 let opaque = OpaqueLeaf::from_leaf(leaf);
155 Self::from_opaque_leaf(opaque)
156 }
157
158 pub fn from_opaque_leaf(opaque: OpaqueLeaf) -> Self {
160 Self(opaque.0)
161 }
162
163 pub fn into_opaque_leaf(self) -> OpaqueLeaf {
165 OpaqueLeaf::from_encoded_leaf(self.0)
167 }
168}
169
170#[derive(RuntimeDebug, Clone, PartialEq)]
180pub enum DataOrHash<H: traits::Hash, L> {
181 Data(L),
183 Hash(H::Output),
185}
186
187impl<H: traits::Hash, L> From<L> for DataOrHash<H, L> {
188 fn from(l: L) -> Self {
189 Self::Data(l)
190 }
191}
192
193mod encoding {
194 use super::*;
195
196 #[derive(codec::Encode, codec::Decode)]
198 enum Either<A, B> {
199 Left(A),
200 Right(B),
201 }
202
203 impl<H: traits::Hash, L: FullLeaf> codec::Encode for DataOrHash<H, L> {
204 fn encode_to<T: codec::Output + ?Sized>(&self, dest: &mut T) {
205 match self {
206 Self::Data(l) => l.using_encoded(
207 |data| Either::<&[u8], &H::Output>::Left(data).encode_to(dest),
208 false,
209 ),
210 Self::Hash(h) => Either::<&[u8], &H::Output>::Right(h).encode_to(dest),
211 }
212 }
213 }
214
215 impl<H: traits::Hash, L: FullLeaf + codec::Decode> codec::Decode for DataOrHash<H, L> {
216 fn decode<I: codec::Input>(value: &mut I) -> Result<Self, codec::Error> {
217 let decoded: Either<Vec<u8>, H::Output> = Either::decode(value)?;
218 Ok(match decoded {
219 Either::Left(l) => DataOrHash::Data(L::decode(&mut &*l)?),
220 Either::Right(r) => DataOrHash::Hash(r),
221 })
222 }
223 }
224}
225
226impl<H: traits::Hash, L: FullLeaf> DataOrHash<H, L> {
227 pub fn hash(&self) -> H::Output {
232 match *self {
233 Self::Data(ref leaf) => leaf.using_encoded(<H as traits::Hash>::hash, true),
234 Self::Hash(ref hash) => *hash,
235 }
236 }
237}
238
239#[derive(RuntimeDebug, Clone, PartialEq)]
251pub struct Compact<H, T> {
252 pub tuple: T,
254 _hash: core::marker::PhantomData<H>,
255}
256
257impl<H, T> core::ops::Deref for Compact<H, T> {
258 type Target = T;
259
260 fn deref(&self) -> &Self::Target {
261 &self.tuple
262 }
263}
264
265impl<H, T> Compact<H, T> {
266 pub fn new(tuple: T) -> Self {
268 Self { tuple, _hash: Default::default() }
269 }
270}
271
272impl<H, T: codec::Decode> codec::Decode for Compact<H, T> {
273 fn decode<I: codec::Input>(value: &mut I) -> Result<Self, codec::Error> {
274 T::decode(value).map(Compact::new)
275 }
276}
277
278macro_rules! impl_leaf_data_for_tuple {
279 ( $( $name:ident : $id:tt ),+ ) => {
280 impl<H, $( $name ),+> FullLeaf for Compact<H, ( $( DataOrHash<H, $name>, )+ )> where
282 H: traits::Hash,
283 $( $name: FullLeaf ),+
284 {
285 fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F, compact: bool) -> R {
286 if compact {
287 codec::Encode::using_encoded(&(
288 $( DataOrHash::<H, $name>::Hash(self.tuple.$id.hash()), )+
289 ), f)
290 } else {
291 codec::Encode::using_encoded(&self.tuple, f)
292 }
293 }
294 }
295
296 impl<H, $( $name ),+> LeafDataProvider for Compact<H, ( $( $name, )+ )> where
300 H: traits::Hash,
301 $( $name: LeafDataProvider ),+
302 {
303 type LeafData = Compact<
304 H,
305 ( $( DataOrHash<H, $name::LeafData>, )+ ),
306 >;
307
308 fn leaf_data() -> Self::LeafData {
309 let tuple = (
310 $( DataOrHash::Data($name::leaf_data()), )+
311 );
312 Compact::new(tuple)
313 }
314 }
315
316 impl<$( $name ),+> LeafDataProvider for ( $( $name, )+ ) where
320 ( $( $name::LeafData, )+ ): FullLeaf,
321 $( $name: LeafDataProvider ),+
322 {
323 type LeafData = ( $( $name::LeafData, )+ );
324
325 fn leaf_data() -> Self::LeafData {
326 (
327 $( $name::leaf_data(), )+
328 )
329 }
330 }
331 }
332}
333
334#[cfg(test)]
336impl<H, A, B> Compact<H, (DataOrHash<H, A>, DataOrHash<H, B>)>
337where
338 H: traits::Hash,
339 A: FullLeaf,
340 B: FullLeaf,
341{
342 pub fn hash(&self) -> H::Output {
344 self.using_encoded(<H as traits::Hash>::hash, true)
345 }
346}
347
348impl_leaf_data_for_tuple!(A:0);
349impl_leaf_data_for_tuple!(A:0, B:1);
350impl_leaf_data_for_tuple!(A:0, B:1, C:2);
351impl_leaf_data_for_tuple!(A:0, B:1, C:2, D:3);
352impl_leaf_data_for_tuple!(A:0, B:1, C:2, D:3, E:4);
353
354#[derive(codec::Encode, codec::Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)]
356pub struct LeafProof<Hash> {
357 pub leaf_indices: Vec<LeafIndex>,
359 pub leaf_count: NodeIndex,
361 pub items: Vec<Hash>,
363}
364
365#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
367#[derive(Encode, Decode, DecodeWithMemTracking, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)]
368pub struct AncestryProof<Hash> {
369 pub prev_peaks: Vec<Hash>,
371 pub prev_leaf_count: u64,
373 pub leaf_count: NodeIndex,
375 pub items: Vec<(u64, Hash)>,
378}
379
380#[cfg_attr(feature = "std", derive(thiserror::Error))]
382#[derive(RuntimeDebug, codec::Encode, codec::Decode, PartialEq, Eq, TypeInfo)]
383pub enum Error {
384 #[cfg_attr(feature = "std", error("Error performing numeric op"))]
386 InvalidNumericOp,
387 #[cfg_attr(feature = "std", error("Error pushing new node"))]
389 Push,
390 #[cfg_attr(feature = "std", error("Error getting new root"))]
392 GetRoot,
393 #[cfg_attr(feature = "std", error("Error committing changes"))]
395 Commit,
396 #[cfg_attr(feature = "std", error("Error generating proof"))]
398 GenerateProof,
399 #[cfg_attr(feature = "std", error("Invalid proof"))]
401 Verify,
402 #[cfg_attr(feature = "std", error("Leaf was not found"))]
404 LeafNotFound,
405 #[cfg_attr(feature = "std", error("MMR pallet not included in runtime"))]
407 PalletNotIncluded,
408 #[cfg_attr(feature = "std", error("Requested leaf index invalid"))]
410 InvalidLeafIndex,
411 #[cfg_attr(feature = "std", error("Provided best known block number invalid"))]
413 InvalidBestKnownBlock,
414}
415
416impl Error {
417 #![allow(unused_variables)]
418 pub fn log_error(self, e: impl fmt::Debug) -> Self {
420 log::error!(
421 target: "runtime::mmr",
422 "[{:?}] MMR error: {:?}",
423 self,
424 e,
425 );
426 self
427 }
428
429 pub fn log_debug(self, e: impl fmt::Debug) -> Self {
431 log::debug!(
432 target: "runtime::mmr",
433 "[{:?}] MMR error: {:?}",
434 self,
435 e,
436 );
437 self
438 }
439}
440
441sp_api::decl_runtime_apis! {
442 #[api_version(3)]
444 pub trait MmrApi<Hash: codec::Codec, BlockNumber: codec::Codec> {
445 fn mmr_root() -> Result<Hash, Error>;
447
448 fn mmr_leaf_count() -> Result<LeafIndex, Error>;
450
451 fn generate_proof(
454 block_numbers: Vec<BlockNumber>,
455 best_known_block_number: Option<BlockNumber>
456 ) -> Result<(Vec<EncodableOpaqueLeaf>, LeafProof<Hash>), Error>;
457
458 fn generate_ancestry_proof(
461 prev_block_number: BlockNumber,
462 best_known_block_number: Option<BlockNumber>,
463 ) -> Result<AncestryProof<Hash>, Error>;
464
465 fn verify_proof(leaves: Vec<EncodableOpaqueLeaf>, proof: LeafProof<Hash>) -> Result<(), Error>;
471
472 fn verify_proof_stateless(root: Hash, leaves: Vec<EncodableOpaqueLeaf>, proof: LeafProof<Hash>)
480 -> Result<(), Error>;
481 }
482}
483
484#[cfg(test)]
485mod tests {
486 use super::*;
487
488 use codec::Decode;
489 use sp_core::H256;
490 use sp_runtime::traits::Keccak256;
491
492 pub(crate) fn hex(s: &str) -> H256 {
493 s.parse().unwrap()
494 }
495
496 type Test = DataOrHash<Keccak256, String>;
497 type TestCompact = Compact<Keccak256, (Test, Test)>;
498 type TestProof = LeafProof<<Keccak256 as traits::Hash>::Output>;
499
500 #[test]
501 fn should_encode_decode_proof() {
502 let proof: TestProof = LeafProof {
504 leaf_indices: vec![5],
505 leaf_count: 10,
506 items: vec![
507 hex("c3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd"),
508 hex("d3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd"),
509 hex("e3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd"),
510 ],
511 };
512
513 let encoded = codec::Encode::encode(&proof);
515 let decoded = TestProof::decode(&mut &*encoded);
516
517 assert_eq!(decoded, Ok(proof));
519 }
520
521 #[test]
522 fn should_encode_decode_correctly_if_no_compact() {
523 let cases = vec![
525 Test::Data("Hello World!".into()),
526 Test::Hash(hex("c3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd")),
527 Test::Data("".into()),
528 Test::Data("3e48d6bcd417fb22e044747242451e2c0f3e602d1bcad2767c34808621956417".into()),
529 ];
530
531 let encoded = cases.iter().map(codec::Encode::encode).collect::<Vec<_>>();
533
534 let decoded = encoded.iter().map(|x| Test::decode(&mut &**x)).collect::<Vec<_>>();
535
536 assert_eq!(
538 decoded,
539 cases.into_iter().map(Result::<_, codec::Error>::Ok).collect::<Vec<_>>()
540 );
541 assert_eq!(
543 &encoded[0],
544 &array_bytes::hex2bytes_unchecked("00343048656c6c6f20576f726c6421")
545 );
546 assert_eq!(
547 encoded[1].as_slice(),
548 array_bytes::hex2bytes_unchecked(
549 "01c3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd"
550 )
551 .as_slice()
552 );
553 }
554
555 #[test]
556 fn should_return_the_hash_correctly() {
557 let a = Test::Data("Hello World!".into());
559 let b = Test::Hash(hex("c3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd"));
560
561 let a = a.hash();
563 let b = b.hash();
564
565 assert_eq!(a, hex("a9c321be8c24ba4dc2bd73f5300bde67dc57228ab8b68b607bb4c39c5374fac9"));
567 assert_eq!(b, hex("c3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd"));
568 }
569
570 #[test]
571 fn compact_should_work() {
572 let a = Test::Data("Hello World!".into());
574 let b = Test::Data("".into());
575
576 let c: TestCompact = Compact::new((a.clone(), b.clone()));
578 let d: TestCompact = Compact::new((Test::Hash(a.hash()), Test::Hash(b.hash())));
579
580 assert_eq!(c.hash(), d.hash());
582 }
583
584 #[test]
585 fn compact_should_encode_decode_correctly() {
586 let a = Test::Data("Hello World!".into());
588 let b = Test::Data("".into());
589
590 let c: TestCompact = Compact::new((a.clone(), b.clone()));
591 let d: TestCompact = Compact::new((Test::Hash(a.hash()), Test::Hash(b.hash())));
592 let cases = vec![c, d.clone()];
593
594 let encoded_compact =
596 cases.iter().map(|c| c.using_encoded(|x| x.to_vec(), true)).collect::<Vec<_>>();
597
598 let encoded =
599 cases.iter().map(|c| c.using_encoded(|x| x.to_vec(), false)).collect::<Vec<_>>();
600
601 let decoded_compact = encoded_compact
602 .iter()
603 .map(|x| TestCompact::decode(&mut &**x))
604 .collect::<Vec<_>>();
605
606 let decoded = encoded.iter().map(|x| TestCompact::decode(&mut &**x)).collect::<Vec<_>>();
607
608 assert_eq!(
610 decoded,
611 cases.into_iter().map(Result::<_, codec::Error>::Ok).collect::<Vec<_>>()
612 );
613
614 assert_eq!(decoded_compact, vec![Ok(d.clone()), Ok(d.clone())]);
615 }
616
617 #[test]
618 fn opaque_leaves_should_be_full_leaf_compatible() {
619 let a = Test::Data("Hello World!".into());
621 let b = Test::Data("".into());
622
623 let c: TestCompact = Compact::new((a.clone(), b.clone()));
624 let d: TestCompact = Compact::new((Test::Hash(a.hash()), Test::Hash(b.hash())));
625 let cases = vec![c, d.clone()];
626
627 let encoded_compact = cases
628 .iter()
629 .map(|c| c.using_encoded(|x| x.to_vec(), true))
630 .map(OpaqueLeaf::from_encoded_leaf)
631 .collect::<Vec<_>>();
632
633 let opaque = cases.iter().map(OpaqueLeaf::from_leaf).collect::<Vec<_>>();
634
635 assert_eq!(encoded_compact, opaque);
637 }
638
639 #[test]
640 fn encode_opaque_leaf_should_be_scale_compatible() {
641 use codec::Encode;
642
643 let a = Test::Data("Hello World!".into());
645 let case1 = EncodableOpaqueLeaf::from_leaf(&a);
646 let case2 = EncodableOpaqueLeaf::from_opaque_leaf(OpaqueLeaf(a.encode()));
647 let case3 = a.encode().encode();
648
649 let encoded = vec![&case1, &case2].into_iter().map(|x| x.encode()).collect::<Vec<_>>();
651 let decoded = vec![&*encoded[0], &*encoded[1], &*case3]
652 .into_iter()
653 .map(|x| EncodableOpaqueLeaf::decode(&mut &*x))
654 .collect::<Vec<_>>();
655
656 assert_eq!(case1, case2);
658 assert_eq!(encoded[0], encoded[1]);
659 assert_eq!(encoded[0], case3);
661
662 assert_eq!(decoded[0], decoded[1]);
663 assert_eq!(decoded[1], decoded[2]);
664 assert_eq!(decoded[0], Ok(case2));
665 assert_eq!(decoded[1], Ok(case1));
666 }
667}