Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Next Next commit
Allow pallet's info to be enumerated
  • Loading branch information
gavofyork committed Oct 18, 2021
commit bdc2aeb11b4d51c647f9b7b0d76770f0e73135e7
4 changes: 2 additions & 2 deletions frame/support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1476,11 +1476,11 @@ pub mod pallet_prelude {
/// * [`traits::OnGenesis`]: contains some logic to write pallet version into storage.
/// * `PalletErrorTypeInfo`: provides the type information for the pallet error, if defined.
///
/// It declare `type Module` type alias for `Pallet`, used by [`construct_runtime`].
/// It declares `type Module` type alias for `Pallet`, used by [`construct_runtime`].
///
/// It implements [`traits::PalletInfoAccess`] on `Pallet` to ease access to pallet
/// informations given by [`frame_support::traits::PalletInfo`].
/// (The implementation use the associated type `frame_system::Config::PalletInfo`).
/// (The implementation uses the associated type `frame_system::Config::PalletInfo`).
///
/// It implements [`traits::StorageInfoTrait`] on `Pallet` which give information about all
/// storages.
Expand Down
2 changes: 1 addition & 1 deletion frame/support/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub use randomness::Randomness;
mod metadata;
pub use metadata::{
CallMetadata, CrateVersion, GetCallMetadata, GetCallName, GetStorageVersion, PalletInfo,
PalletInfoAccess, StorageVersion, STORAGE_VERSION_STORAGE_KEY_POSTFIX,
PalletInfoAccess, StorageVersion, STORAGE_VERSION_STORAGE_KEY_POSTFIX, PalletInfoData,
};

mod hooks;
Expand Down
64 changes: 64 additions & 0 deletions frame/support/src/traits/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

use codec::{Decode, Encode};
use sp_runtime::RuntimeDebug;
use impl_trait_for_tuples::impl_for_tuples;

/// Provides information about the pallet itself and its setup in the runtime.
///
Expand All @@ -35,6 +36,19 @@ pub trait PalletInfo {
fn crate_version<P: 'static>() -> Option<CrateVersion>;
}

/// Information regarding an instance of a pallet.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug)]
pub struct PalletInfoData {
/// Index of the pallet as configured in the runtime.
pub index: usize,
/// Name of the pallet as configured in the runtime.
pub name: &'static str,
/// Name of the Rust module containing the pallet.
pub module_name: &'static str,
/// Version of the crate containing the pallet.
pub crate_version: CrateVersion,
}

/// Provides information about the pallet itself and its setup in the runtime.
///
/// Declare some information and access the information provided by [`PalletInfo`] for a specific
Expand All @@ -48,6 +62,35 @@ pub trait PalletInfoAccess {
fn module_name() -> &'static str;
/// Version of the crate containing the pallet.
fn crate_version() -> CrateVersion;
/// Get all information at once.
fn info() -> PalletInfoData {
PalletInfoData {
index: Self::index(),
name: Self::name(),
module_name: Self::module_name(),
crate_version: Self::crate_version(),
}
}
/// All pallet information that this type represents. For tuples, this can be len more than 1.
fn infos() -> Vec<PalletInfoData> {
vec![Self::info()]
}
}

#[impl_for_tuples(60)]
impl PalletInfoAccess for Tuple {
fn index() -> usize { unreachable!("fields not available on a tuple") }
fn name() -> &'static str { unreachable!("fields not available on a tuple") }
fn module_name() -> &'static str { unreachable!("fields not available on a tuple") }
fn crate_version() -> CrateVersion { unreachable!("fields not available on a tuple") }
fn info() -> PalletInfoData { unreachable!("fields not available on a tuple") }
fn infos() -> Vec<PalletInfoData> {
let mut result = vec![];
for_tuples!( #(
result.extend(Tuple::infos());
)* );
result
}
}

/// The function and pallet name of the Call.
Expand Down Expand Up @@ -206,6 +249,27 @@ pub trait GetStorageVersion {
mod tests {
use super::*;

struct Pallet1;
impl PalletInfoAccess for Pallet1 {
fn index() -> usize { 1 }
fn name() -> &'static str { "Pallat1" }
fn module_name() -> &'static str { "pallet1" }
fn crate_version() -> CrateVersion { CrateVersion::new(1, 0, 0) }
}
struct Pallet2;
impl PalletInfoAccess for Pallet2 {
fn index() -> usize { 2 }
fn name() -> &'static str { "Pallat2" }
fn module_name() -> &'static str { "pallet2" }
fn crate_version() -> CrateVersion { CrateVersion::new(1, 0, 0) }
}

#[test]
fn check_tuples() {
use PalletInfoAccess;
assert!(<(Pallet1, Pallet2,)>::infos().len() == 2);
}

#[test]
fn check_storage_version_ordering() {
let version = StorageVersion::new(1);
Expand Down
33 changes: 33 additions & 0 deletions frame/support/test/tests/pallet_instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,39 @@ fn storage_expand() {
});
}

#[test]
fn pallet_metadata_expands() {
use frame_support::traits::{PalletInfoAccess, PalletInfoData, CrateVersion};
let mut infos = AllPallets::infos();
infos.sort_by_key(|x| x.index);
assert_eq!(infos, vec![
PalletInfoData {
index: 1,
name: "Example",
module_name: "pallet",
crate_version: CrateVersion { major: 3, minor: 0, patch: 0 },
},
PalletInfoData {
index: 2,
name: "Instance1Example",
module_name: "pallet",
crate_version: CrateVersion { major: 3, minor: 0, patch: 0 },
},
PalletInfoData {
index: 3,
name: "Example2",
module_name: "pallet2",
crate_version: CrateVersion { major: 3, minor: 0, patch: 0 },
},
PalletInfoData {
index: 4,
name: "Instance1Example2",
module_name: "pallet2",
crate_version: CrateVersion { major: 3, minor: 0, patch: 0 },
},
]);
}

#[test]
fn pallet_hooks_expand() {
TestExternalities::default().execute_with(|| {
Expand Down