pallet_subspace_mmr/
lib.rs

1//! Pallet that provides necessary Leaf data for MMR.
2
3#![cfg_attr(not(feature = "std"), no_std)]
4
5use frame_system::pallet_prelude::BlockNumberFor;
6pub use pallet::*;
7use sp_core::Get;
8use sp_mmr_primitives::{LeafDataProvider, OnNewRoot};
9use sp_runtime::traits::{CheckedSub, One};
10use sp_subspace_mmr::subspace_mmr_runtime_interface::get_mmr_leaf_data;
11use sp_subspace_mmr::{LeafDataV0, MmrLeaf};
12
13#[frame_support::pallet]
14mod pallet {
15    use frame_support::pallet_prelude::*;
16    use frame_support::Parameter;
17    use frame_system::pallet_prelude::BlockNumberFor;
18    use sp_core::H256;
19
20    #[pallet::pallet]
21    pub struct Pallet<T>(_);
22
23    #[pallet::config]
24    pub trait Config: frame_system::Config<Hash: Into<H256> + From<H256>> {
25        type MmrRootHash: Parameter + Copy + MaxEncodedLen;
26
27        /// The number of mmr root hashes to store in the runtime. It will be used to verify mmr
28        /// proof statelessly and the number of roots stored here represents the number of blocks
29        /// for which the mmr proof is valid since it is generated. After that the mmr proof
30        /// will be expired and the prover needs to re-generate the proof.
31        type MmrRootHashCount: Get<u32>;
32    }
33
34    /// Map of block numbers to mmr root hashes.
35    #[pallet::storage]
36    #[pallet::getter(fn mmr_root_hash)]
37    pub type MmrRootHashes<T: Config> =
38        StorageMap<_, Twox64Concat, BlockNumberFor<T>, T::MmrRootHash, OptionQuery>;
39}
40
41impl<T: Config> OnNewRoot<T::MmrRootHash> for Pallet<T> {
42    fn on_new_root(root: &T::MmrRootHash) {
43        let block_number = frame_system::Pallet::<T>::block_number();
44        <MmrRootHashes<T>>::insert(block_number, *root);
45        if let Some(to_prune) = block_number.checked_sub(&T::MmrRootHashCount::get().into()) {
46            <MmrRootHashes<T>>::remove(to_prune);
47        }
48    }
49}
50
51impl<T: Config> LeafDataProvider for Pallet<T> {
52    type LeafData = MmrLeaf<BlockNumberFor<T>, T::Hash>;
53
54    fn leaf_data() -> Self::LeafData {
55        let block_number = frame_system::Pallet::<T>::block_number()
56            .checked_sub(&One::one())
57            .expect("`block_number` will always be >= 1; qed");
58        let block_hash = frame_system::Pallet::<T>::parent_hash();
59        let leaf_data = get_mmr_leaf_data(block_hash.into())
60            .expect("leaf data for parent hash must always be derived; qed");
61        MmrLeaf::V0(LeafDataV0 {
62            block_number,
63            block_hash,
64            state_root: leaf_data.state_root.into(),
65            extrinsics_root: leaf_data.extrinsics_root.into(),
66        })
67    }
68}