mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-18 00:11:01 +00:00
Migrate pallet-mmr to the new pallet attribute macro (#9181)
* Migrate pallet-mmr to the new pallet attribute macro Signed-off-by: koushiro <koushiro.cqx@gmail.com> * fix typo Signed-off-by: koushiro <koushiro.cqx@gmail.com> * use instance macro Co-authored-by: thiolliere <gui.thiolliere@gmail.com>
This commit is contained in:
@@ -58,10 +58,7 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use codec::Encode;
|
||||
use frame_support::{
|
||||
decl_module, decl_storage,
|
||||
weights::Weight,
|
||||
};
|
||||
use frame_support::weights::Weight;
|
||||
use sp_runtime::traits;
|
||||
|
||||
mod default_weights;
|
||||
@@ -74,86 +71,105 @@ mod mock;
|
||||
mod tests;
|
||||
|
||||
pub use pallet_mmr_primitives as primitives;
|
||||
pub use pallet::*;
|
||||
|
||||
pub trait WeightInfo {
|
||||
fn on_initialize(peaks: u64) -> Weight;
|
||||
}
|
||||
|
||||
/// This pallet's configuration trait
|
||||
pub trait Config<I = DefaultInstance>: frame_system::Config {
|
||||
/// Prefix for elements stored in the Off-chain DB via Indexing API.
|
||||
///
|
||||
/// Each node of the MMR is inserted both on-chain and off-chain via Indexing API.
|
||||
/// The former does not store full leaf content, just it's compact version (hash),
|
||||
/// and some of the inner mmr nodes might be pruned from on-chain storage.
|
||||
/// The later will contain all the entries in their full form.
|
||||
///
|
||||
/// Each node is stored in the Off-chain DB under key derived from the [`Self::INDEXING_PREFIX`] and
|
||||
/// it's in-tree index (MMR position).
|
||||
const INDEXING_PREFIX: &'static [u8];
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
use frame_support::pallet_prelude::*;
|
||||
use frame_system::pallet_prelude::*;
|
||||
use super::*;
|
||||
|
||||
/// A hasher type for MMR.
|
||||
///
|
||||
/// To construct trie nodes that result in merging (bagging) two peaks, depending on the node
|
||||
/// kind we take either:
|
||||
/// - The node (hash) itself if it's an inner node.
|
||||
/// - The hash of SCALE-encoding of the leaf data if it's a leaf node.
|
||||
///
|
||||
/// Then we create a tuple of these two hashes, SCALE-encode it (concatenate) and
|
||||
/// hash, to obtain a new MMR inner node - the new peak.
|
||||
type Hashing: traits::Hash<Output = <Self as Config<I>>::Hash>;
|
||||
#[pallet::pallet]
|
||||
#[pallet::generate_store(pub(super) trait Store)]
|
||||
pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);
|
||||
|
||||
/// The hashing output type.
|
||||
///
|
||||
/// This type is actually going to be stored in the MMR.
|
||||
/// Required to be provided again, to satisfy trait bounds for storage items.
|
||||
type Hash: traits::Member + traits::MaybeSerializeDeserialize + sp_std::fmt::Debug
|
||||
+ sp_std::hash::Hash + AsRef<[u8]> + AsMut<[u8]> + Copy + Default + codec::Codec
|
||||
+ codec::EncodeLike;
|
||||
|
||||
/// Data stored in the leaf nodes.
|
||||
///
|
||||
/// The [LeafData](primitives::LeafDataProvider) is responsible for returning the entire leaf
|
||||
/// data that will be inserted to the MMR.
|
||||
/// [LeafDataProvider](primitives::LeafDataProvider)s can be composed into tuples to put
|
||||
/// multiple elements into the tree. In such a case it might be worth using [primitives::Compact]
|
||||
/// to make MMR proof for one element of the tuple leaner.
|
||||
///
|
||||
/// Note that the leaf at each block MUST be unique. You may want to include a block hash or block
|
||||
/// number as an easiest way to ensure that.
|
||||
type LeafData: primitives::LeafDataProvider;
|
||||
|
||||
/// A hook to act on the new MMR root.
|
||||
///
|
||||
/// For some applications it might be beneficial to make the MMR root available externally
|
||||
/// apart from having it in the storage. For instance you might output it in the header digest
|
||||
/// (see [`frame_system::Pallet::deposit_log`]) to make it available for Light Clients.
|
||||
/// Hook complexity should be `O(1)`.
|
||||
type OnNewRoot: primitives::OnNewRoot<<Self as Config<I>>::Hash>;
|
||||
|
||||
/// Weights for this pallet.
|
||||
type WeightInfo: WeightInfo;
|
||||
}
|
||||
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Config<I>, I: Instance = DefaultInstance> as MerkleMountainRange {
|
||||
/// Latest MMR Root hash.
|
||||
pub RootHash get(fn mmr_root_hash): <T as Config<I>>::Hash;
|
||||
|
||||
/// Current size of the MMR (number of leaves).
|
||||
pub NumberOfLeaves get(fn mmr_leaves): u64;
|
||||
|
||||
/// Hashes of the nodes in the MMR.
|
||||
/// This pallet's configuration trait
|
||||
#[pallet::config]
|
||||
pub trait Config<I: 'static = ()>: frame_system::Config {
|
||||
/// Prefix for elements stored in the Off-chain DB via Indexing API.
|
||||
///
|
||||
/// Note this collection only contains MMR peaks, the inner nodes (and leaves)
|
||||
/// are pruned and only stored in the Offchain DB.
|
||||
pub Nodes get(fn mmr_peak): map hasher(identity) u64 => Option<<T as Config<I>>::Hash>;
|
||||
}
|
||||
}
|
||||
/// Each node of the MMR is inserted both on-chain and off-chain via Indexing API.
|
||||
/// The former does not store full leaf content, just it's compact version (hash),
|
||||
/// and some of the inner mmr nodes might be pruned from on-chain storage.
|
||||
/// The latter will contain all the entries in their full form.
|
||||
///
|
||||
/// Each node is stored in the Off-chain DB under key derived from the [`Self::INDEXING_PREFIX`] and
|
||||
/// it's in-tree index (MMR position).
|
||||
const INDEXING_PREFIX: &'static [u8];
|
||||
|
||||
decl_module! {
|
||||
/// A public part of the pallet.
|
||||
pub struct Module<T: Config<I>, I: Instance = DefaultInstance> for enum Call where origin: T::Origin {
|
||||
/// A hasher type for MMR.
|
||||
///
|
||||
/// To construct trie nodes that result in merging (bagging) two peaks, depending on the node
|
||||
/// kind we take either:
|
||||
/// - The node (hash) itself if it's an inner node.
|
||||
/// - The hash of SCALE-encoding of the leaf data if it's a leaf node.
|
||||
///
|
||||
/// Then we create a tuple of these two hashes, SCALE-encode it (concatenate) and
|
||||
/// hash, to obtain a new MMR inner node - the new peak.
|
||||
type Hashing: traits::Hash<Output = <Self as Config<I>>::Hash>;
|
||||
|
||||
/// The hashing output type.
|
||||
///
|
||||
/// This type is actually going to be stored in the MMR.
|
||||
/// Required to be provided again, to satisfy trait bounds for storage items.
|
||||
type Hash: traits::Member + traits::MaybeSerializeDeserialize + sp_std::fmt::Debug
|
||||
+ sp_std::hash::Hash + AsRef<[u8]> + AsMut<[u8]> + Copy + Default + codec::Codec
|
||||
+ codec::EncodeLike;
|
||||
|
||||
/// Data stored in the leaf nodes.
|
||||
///
|
||||
/// The [LeafData](primitives::LeafDataProvider) is responsible for returning the entire leaf
|
||||
/// data that will be inserted to the MMR.
|
||||
/// [LeafDataProvider](primitives::LeafDataProvider)s can be composed into tuples to put
|
||||
/// multiple elements into the tree. In such a case it might be worth using [primitives::Compact]
|
||||
/// to make MMR proof for one element of the tuple leaner.
|
||||
///
|
||||
/// Note that the leaf at each block MUST be unique. You may want to include a block hash or block
|
||||
/// number as an easiest way to ensure that.
|
||||
type LeafData: primitives::LeafDataProvider;
|
||||
|
||||
/// A hook to act on the new MMR root.
|
||||
///
|
||||
/// For some applications it might be beneficial to make the MMR root available externally
|
||||
/// apart from having it in the storage. For instance you might output it in the header digest
|
||||
/// (see [`frame_system::Pallet::deposit_log`]) to make it available for Light Clients.
|
||||
/// Hook complexity should be `O(1)`.
|
||||
type OnNewRoot: primitives::OnNewRoot<<Self as Config<I>>::Hash>;
|
||||
|
||||
/// Weights for this pallet.
|
||||
type WeightInfo: WeightInfo;
|
||||
}
|
||||
|
||||
/// Latest MMR Root hash.
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn mmr_root_hash)]
|
||||
pub type RootHash<T: Config<I>, I: 'static = ()> = StorageValue<_, <T as Config<I>>::Hash, ValueQuery>;
|
||||
|
||||
/// Current size of the MMR (number of leaves).
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn mmr_leaves)]
|
||||
pub type NumberOfLeaves<T, I = ()> = StorageValue<_, u64, ValueQuery>;
|
||||
|
||||
/// Hashes of the nodes in the MMR.
|
||||
///
|
||||
/// Note this collection only contains MMR peaks, the inner nodes (and leaves)
|
||||
/// are pruned and only stored in the Offchain DB.
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn mmr_peak)]
|
||||
pub type Nodes<T: Config<I>, I: 'static = ()> = StorageMap<
|
||||
_,
|
||||
Identity,
|
||||
u64,
|
||||
<T as Config<I>>::Hash,
|
||||
OptionQuery
|
||||
>;
|
||||
|
||||
#[pallet::hooks]
|
||||
impl<T: Config<I>, I: 'static> Hooks<BlockNumberFor<T>> for Pallet<T, I> {
|
||||
fn on_initialize(_n: T::BlockNumber) -> Weight {
|
||||
use primitives::LeafDataProvider;
|
||||
let leaves = Self::mmr_leaves();
|
||||
@@ -167,7 +183,7 @@ decl_module! {
|
||||
let (leaves, root) = mmr.finalize().expect("MMR finalize never fails.");
|
||||
<T::OnNewRoot as primitives::OnNewRoot<_>>::on_new_root(&root);
|
||||
|
||||
<NumberOfLeaves>::put(leaves);
|
||||
<NumberOfLeaves<T, I>>::put(leaves);
|
||||
<RootHash<T, I>>::put(root);
|
||||
|
||||
let peaks_after = mmr::utils::NodesUtils::new(leaves).number_of_peaks();
|
||||
@@ -207,7 +223,7 @@ pub fn verify_leaf_proof<H, L>(
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: Instance> Module<T, I> {
|
||||
impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
fn offchain_key(pos: u64) -> sp_std::prelude::Vec<u8> {
|
||||
(T::INDEXING_PREFIX, pos).encode()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user