sp_subspace_mmr/
lib.rs

1//! Primitives for Subspace MMR.
2
3#![cfg_attr(not(feature = "std"), no_std)]
4#![feature(result_flattening)]
5
6#[cfg(all(feature = "std", feature = "runtime-benchmarks"))]
7pub mod benchmarking;
8#[cfg(feature = "std")]
9pub mod host_functions;
10mod runtime_interface;
11
12#[cfg(feature = "std")]
13pub use runtime_interface::domain_mmr_runtime_interface::HostFunctions as DomainHostFunctions;
14#[cfg(feature = "std")]
15pub use runtime_interface::subspace_mmr_runtime_interface::HostFunctions;
16pub use runtime_interface::{domain_mmr_runtime_interface, subspace_mmr_runtime_interface};
17
18#[cfg(not(feature = "std"))]
19extern crate alloc;
20
21use parity_scale_codec::{Decode, Encode};
22use scale_info::TypeInfo;
23use sp_mmr_primitives::{EncodableOpaqueLeaf, LeafProof as MmrProof};
24
25/// MMR leaf structure
26#[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone)]
27pub enum MmrLeaf<BlockNumber, Hash> {
28    /// V0 version of leaf data
29    V0(LeafDataV0<BlockNumber, Hash>),
30}
31
32impl<BlockNumber: Clone, Hash: Clone> MmrLeaf<BlockNumber, Hash> {
33    pub fn state_root(&self) -> Hash {
34        match self {
35            MmrLeaf::V0(leaf) => leaf.state_root.clone(),
36        }
37    }
38
39    pub fn block_number(&self) -> BlockNumber {
40        match self {
41            MmrLeaf::V0(leaf) => leaf.block_number.clone(),
42        }
43    }
44}
45
46/// MMR v0 leaf data
47#[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone)]
48pub struct LeafDataV0<BlockNumber, Hash> {
49    pub block_number: BlockNumber,
50    pub block_hash: Hash,
51    /// Can be used to prove specific storage after block was pruned
52    pub state_root: Hash,
53    /// Can be used to prove block body
54    pub extrinsics_root: Hash,
55}
56
57/// Consensus chain MMR leaf and its Proof at specific block.
58///
59/// The verifier is not required to contains any the MMR offchain data but this proof
60/// will be expired after `N` blocks where `N` is the number of MMR root stored in the
61// consensus chain runtime.
62#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq, TypeInfo)]
63pub struct ConsensusChainMmrLeafProof<CBlockNumber, CBlockHash, MmrHash> {
64    /// Consensus block info from which this proof was generated.
65    pub consensus_block_number: CBlockNumber,
66    pub consensus_block_hash: CBlockHash,
67    /// Encoded MMR leaf
68    pub opaque_mmr_leaf: EncodableOpaqueLeaf,
69    /// MMR proof for the leaf above.
70    pub proof: MmrProof<MmrHash>,
71}
72
73/// Trait to verify MMR proofs
74pub trait MmrProofVerifier<MmrHash, CBlockNumber: Decode, CBlockHash: Decode> {
75    /// Returns consensus state root if the given MMR proof is valid
76    fn verify_proof_and_extract_leaf(
77        mmr_leaf_proof: ConsensusChainMmrLeafProof<CBlockNumber, CBlockHash, MmrHash>,
78    ) -> Option<MmrLeaf<CBlockNumber, CBlockHash>>;
79
80    fn verify_proof_stateless(
81        _mmr_root: MmrHash,
82        _mmr_leaf_proof: ConsensusChainMmrLeafProof<CBlockNumber, CBlockHash, MmrHash>,
83    ) -> Option<MmrLeaf<CBlockNumber, CBlockHash>> {
84        None
85    }
86
87    fn extract_leaf_without_verifying(
88        mmr_leaf_proof: ConsensusChainMmrLeafProof<CBlockNumber, CBlockHash, MmrHash>,
89    ) -> Option<MmrLeaf<CBlockNumber, CBlockHash>> {
90        mmr_leaf_proof
91            .opaque_mmr_leaf
92            .into_opaque_leaf()
93            .try_decode()
94    }
95}
96
97impl<MmrHash, CBlockNumber: Decode, CBlockHash: Decode>
98    MmrProofVerifier<MmrHash, CBlockNumber, CBlockHash> for ()
99{
100    fn verify_proof_and_extract_leaf(
101        _mmr_leaf_proof: ConsensusChainMmrLeafProof<CBlockNumber, CBlockHash, MmrHash>,
102    ) -> Option<MmrLeaf<CBlockNumber, CBlockHash>> {
103        None
104    }
105}