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#[derive(Encode, Decode, DecodeWithMemTracking, RuntimeDebug, 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(RuntimeDebug, 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(2)]
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 verify_proof(leaves: Vec<EncodableOpaqueLeaf>, proof: LeafProof<Hash>) -> Result<(), Error>;
463
464 fn verify_proof_stateless(root: Hash, leaves: Vec<EncodableOpaqueLeaf>, proof: LeafProof<Hash>)
472 -> Result<(), Error>;
473 }
474}
475
476#[cfg(test)]
477mod tests {
478 use super::*;
479
480 use codec::Decode;
481 use sp_core::H256;
482 use sp_runtime::traits::Keccak256;
483
484 pub(crate) fn hex(s: &str) -> H256 {
485 s.parse().unwrap()
486 }
487
488 type Test = DataOrHash<Keccak256, String>;
489 type TestCompact = Compact<Keccak256, (Test, Test)>;
490 type TestProof = LeafProof<<Keccak256 as traits::Hash>::Output>;
491
492 #[test]
493 fn should_encode_decode_proof() {
494 let proof: TestProof = LeafProof {
496 leaf_indices: vec![5],
497 leaf_count: 10,
498 items: vec![
499 hex("c3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd"),
500 hex("d3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd"),
501 hex("e3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd"),
502 ],
503 };
504
505 let encoded = codec::Encode::encode(&proof);
507 let decoded = TestProof::decode(&mut &*encoded);
508
509 assert_eq!(decoded, Ok(proof));
511 }
512
513 #[test]
514 fn should_encode_decode_correctly_if_no_compact() {
515 let cases = vec![
517 Test::Data("Hello World!".into()),
518 Test::Hash(hex("c3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd")),
519 Test::Data("".into()),
520 Test::Data("3e48d6bcd417fb22e044747242451e2c0f3e602d1bcad2767c34808621956417".into()),
521 ];
522
523 let encoded = cases.iter().map(codec::Encode::encode).collect::<Vec<_>>();
525
526 let decoded = encoded.iter().map(|x| Test::decode(&mut &**x)).collect::<Vec<_>>();
527
528 assert_eq!(
530 decoded,
531 cases.into_iter().map(Result::<_, codec::Error>::Ok).collect::<Vec<_>>()
532 );
533 assert_eq!(
535 &encoded[0],
536 &array_bytes::hex2bytes_unchecked("00343048656c6c6f20576f726c6421")
537 );
538 assert_eq!(
539 encoded[1].as_slice(),
540 array_bytes::hex2bytes_unchecked(
541 "01c3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd"
542 )
543 .as_slice()
544 );
545 }
546
547 #[test]
548 fn should_return_the_hash_correctly() {
549 let a = Test::Data("Hello World!".into());
551 let b = Test::Hash(hex("c3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd"));
552
553 let a = a.hash();
555 let b = b.hash();
556
557 assert_eq!(a, hex("a9c321be8c24ba4dc2bd73f5300bde67dc57228ab8b68b607bb4c39c5374fac9"));
559 assert_eq!(b, hex("c3e7ba6b511162fead58f2c8b5764ce869ed1118011ac37392522ed16720bbcd"));
560 }
561
562 #[test]
563 fn compact_should_work() {
564 let a = Test::Data("Hello World!".into());
566 let b = Test::Data("".into());
567
568 let c: TestCompact = Compact::new((a.clone(), b.clone()));
570 let d: TestCompact = Compact::new((Test::Hash(a.hash()), Test::Hash(b.hash())));
571
572 assert_eq!(c.hash(), d.hash());
574 }
575
576 #[test]
577 fn compact_should_encode_decode_correctly() {
578 let a = Test::Data("Hello World!".into());
580 let b = Test::Data("".into());
581
582 let c: TestCompact = Compact::new((a.clone(), b.clone()));
583 let d: TestCompact = Compact::new((Test::Hash(a.hash()), Test::Hash(b.hash())));
584 let cases = vec![c, d.clone()];
585
586 let encoded_compact =
588 cases.iter().map(|c| c.using_encoded(|x| x.to_vec(), true)).collect::<Vec<_>>();
589
590 let encoded =
591 cases.iter().map(|c| c.using_encoded(|x| x.to_vec(), false)).collect::<Vec<_>>();
592
593 let decoded_compact = encoded_compact
594 .iter()
595 .map(|x| TestCompact::decode(&mut &**x))
596 .collect::<Vec<_>>();
597
598 let decoded = encoded.iter().map(|x| TestCompact::decode(&mut &**x)).collect::<Vec<_>>();
599
600 assert_eq!(
602 decoded,
603 cases.into_iter().map(Result::<_, codec::Error>::Ok).collect::<Vec<_>>()
604 );
605
606 assert_eq!(decoded_compact, vec![Ok(d.clone()), Ok(d.clone())]);
607 }
608
609 #[test]
610 fn opaque_leaves_should_be_full_leaf_compatible() {
611 let a = Test::Data("Hello World!".into());
613 let b = Test::Data("".into());
614
615 let c: TestCompact = Compact::new((a.clone(), b.clone()));
616 let d: TestCompact = Compact::new((Test::Hash(a.hash()), Test::Hash(b.hash())));
617 let cases = vec![c, d.clone()];
618
619 let encoded_compact = cases
620 .iter()
621 .map(|c| c.using_encoded(|x| x.to_vec(), true))
622 .map(OpaqueLeaf::from_encoded_leaf)
623 .collect::<Vec<_>>();
624
625 let opaque = cases.iter().map(OpaqueLeaf::from_leaf).collect::<Vec<_>>();
626
627 assert_eq!(encoded_compact, opaque);
629 }
630
631 #[test]
632 fn encode_opaque_leaf_should_be_scale_compatible() {
633 use codec::Encode;
634
635 let a = Test::Data("Hello World!".into());
637 let case1 = EncodableOpaqueLeaf::from_leaf(&a);
638 let case2 = EncodableOpaqueLeaf::from_opaque_leaf(OpaqueLeaf(a.encode()));
639 let case3 = a.encode().encode();
640
641 let encoded = vec![&case1, &case2].into_iter().map(|x| x.encode()).collect::<Vec<_>>();
643 let decoded = vec![&*encoded[0], &*encoded[1], &*case3]
644 .into_iter()
645 .map(|x| EncodableOpaqueLeaf::decode(&mut &*x))
646 .collect::<Vec<_>>();
647
648 assert_eq!(case1, case2);
650 assert_eq!(encoded[0], encoded[1]);
651 assert_eq!(encoded[0], case3);
653
654 assert_eq!(decoded[0], decoded[1]);
655 assert_eq!(decoded[1], decoded[2]);
656 assert_eq!(decoded[0], Ok(case2));
657 assert_eq!(decoded[1], Ok(case1));
658 }
659}