Skip to content

Commit

Permalink
Migrate pallet-utility to pallet attribute macro. (paritytech#8326)
Browse files Browse the repository at this point in the history
* Migrate pallet-utility to pallet attribute macro.

* Replace 'Module' with 'Pallet' in benchmarking.
  • Loading branch information
shaunxw authored and hirschenberger committed Apr 14, 2021
1 parent 01fb1c6 commit aa82655
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 53 deletions.
2 changes: 1 addition & 1 deletion frame/utility/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ benchmarks! {
}

impl_benchmark_test_suite!(
Module,
Pallet,
crate::tests::new_test_ext(),
crate::tests::Test,
);
119 changes: 69 additions & 50 deletions frame/utility/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//! # Utility Module
//! A stateless module with helpers for dispatch management which does no re-authentication.
//! # Utility Pallet
//! A stateless pallet with helpers for dispatch management which does no re-authentication.
//!
//! - [`Config`]
//! - [`Call`]
//!
//! ## Overview
//!
//! This module contains two basic pieces of functionality:
//! This pallet contains two basic pieces of functionality:
//! - Batch dispatch: A stateless operation, allowing any origin to execute multiple calls in a
//! single dispatch. This can be useful to amalgamate proposals, combining `set_code` with
//! corresponding `set_storage`s, for efficient multiple payouts with just a single signature
Expand All @@ -34,9 +34,9 @@
//! need multiple distinct accounts (e.g. as controllers for many staking accounts), but where
//! it's perfectly fine to have each of them controlled by the same underlying keypair.
//! Derivative accounts are, for the purposes of proxy filtering considered exactly the same as
//! the oigin and are thus hampered with the origin's filters.
//! the origin and are thus hampered with the origin's filters.
//!
//! Since proxy filters are respected in all dispatches of this module, it should never need to be
//! Since proxy filters are respected in all dispatches of this pallet, it should never need to be
//! filtered by any proxy.
//!
//! ## Interface
Expand All @@ -60,58 +60,58 @@ use sp_std::prelude::*;
use codec::{Encode, Decode};
use sp_core::TypeId;
use sp_io::hashing::blake2_256;
use frame_support::{decl_module, decl_event, decl_storage, Parameter, transactional};
use frame_support::{
traits::{OriginTrait, UnfilteredDispatchable, Get},
weights::{Weight, GetDispatchInfo, DispatchClass, extract_actual_weight},
dispatch::{PostDispatchInfo, DispatchResultWithPostInfo},
transactional,
traits::{OriginTrait, UnfilteredDispatchable},
weights::{GetDispatchInfo, extract_actual_weight},
dispatch::PostDispatchInfo,
};
use frame_system::{ensure_signed, ensure_root};
use sp_runtime::{DispatchError, traits::Dispatchable};
use sp_runtime::traits::Dispatchable;
pub use weights::WeightInfo;

/// Configuration trait.
pub trait Config: frame_system::Config {
/// The overarching event type.
type Event: From<Event> + Into<<Self as frame_system::Config>::Event>;
pub use pallet::*;

/// The overarching call type.
type Call: Parameter + Dispatchable<Origin=Self::Origin, PostInfo=PostDispatchInfo>
+ GetDispatchInfo + From<frame_system::Call<Self>>
+ UnfilteredDispatchable<Origin=Self::Origin>;
#[frame_support::pallet]
pub mod pallet {
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use super::*;

/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;
}
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);

decl_storage! {
trait Store for Module<T: Config> as Utility {}
}

decl_event! {
/// Events type.
/// Configuration trait.
#[pallet::config]
pub trait Config: frame_system::Config {
/// The overarching event type.
type Event: From<Event> + IsType<<Self as frame_system::Config>::Event>;

/// The overarching call type.
type Call: Parameter + Dispatchable<Origin=Self::Origin, PostInfo=PostDispatchInfo>
+ GetDispatchInfo + From<frame_system::Call<Self>>
+ UnfilteredDispatchable<Origin=Self::Origin>;

/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;
}

#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event {
/// Batch of dispatches did not complete fully. Index of first failing dispatch given, as
/// well as the error. \[index, error\]
BatchInterrupted(u32, DispatchError),
/// Batch of dispatches completed fully with no error.
BatchCompleted,
}
}

/// A module identifier. These are per module and should be stored in a registry somewhere.
#[derive(Clone, Copy, Eq, PartialEq, Encode, Decode)]
struct IndexedUtilityModuleId(u16);

impl TypeId for IndexedUtilityModuleId {
const TYPE_ID: [u8; 4] = *b"suba";
}

decl_module! {
pub struct Module<T: Config> for enum Call where origin: T::Origin {
/// Deposit one of this module's events by using the default implementation.
fn deposit_event() = default;
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}

#[pallet::call]
impl<T: Config> Pallet<T> {
/// Send a batch of dispatch calls.
///
/// May be called from any origin.
Expand All @@ -130,7 +130,7 @@ decl_module! {
/// `BatchInterrupted` event is deposited, along with the number of successful calls made
/// and the error of the failed call. If all were successful, then the `BatchCompleted`
/// event is deposited.
#[weight = {
#[pallet::weight({
let dispatch_infos = calls.iter().map(|call| call.get_dispatch_info()).collect::<Vec<_>>();
let dispatch_weight = dispatch_infos.iter()
.map(|di| di.weight)
Expand All @@ -147,8 +147,11 @@ decl_module! {
}
};
(dispatch_weight, dispatch_class)
}]
fn batch(origin, calls: Vec<<T as Config>::Call>) -> DispatchResultWithPostInfo {
})]
pub fn batch(
origin: OriginFor<T>,
calls: Vec<<T as Config>::Call>,
) -> DispatchResultWithPostInfo {
let is_root = ensure_root(origin.clone()).is_ok();
let calls_len = calls.len();
// Track the actual weight of each of the batch calls.
Expand Down Expand Up @@ -189,7 +192,7 @@ decl_module! {
/// NOTE: Prior to version *12, this was called `as_limited_sub`.
///
/// The dispatch origin for this call must be _Signed_.
#[weight = {
#[pallet::weight({
let dispatch_info = call.get_dispatch_info();
(
T::WeightInfo::as_derivative()
Expand All @@ -198,8 +201,12 @@ decl_module! {
.saturating_add(T::DbWeight::get().reads_writes(1, 1)),
dispatch_info.class,
)
}]
fn as_derivative(origin, index: u16, call: Box<<T as Config>::Call>) -> DispatchResultWithPostInfo {
})]
pub fn as_derivative(
origin: OriginFor<T>,
index: u16,
call: Box<<T as Config>::Call>,
) -> DispatchResultWithPostInfo {
let mut origin = origin;
let who = ensure_signed(origin.clone())?;
let pseudonym = Self::derivative_account_id(who, index);
Expand Down Expand Up @@ -229,7 +236,7 @@ decl_module! {
/// # <weight>
/// - Complexity: O(C) where C is the number of calls to be batched.
/// # </weight>
#[weight = {
#[pallet::weight({
let dispatch_infos = calls.iter().map(|call| call.get_dispatch_info()).collect::<Vec<_>>();
let dispatch_weight = dispatch_infos.iter()
.map(|di| di.weight)
Expand All @@ -246,9 +253,12 @@ decl_module! {
}
};
(dispatch_weight, dispatch_class)
}]
})]
#[transactional]
fn batch_all(origin, calls: Vec<<T as Config>::Call>) -> DispatchResultWithPostInfo {
pub fn batch_all(
origin: OriginFor<T>,
calls: Vec<<T as Config>::Call>,
) -> DispatchResultWithPostInfo {
let is_root = ensure_root(origin.clone()).is_ok();
let calls_len = calls.len();
// Track the actual weight of each of the batch calls.
Expand Down Expand Up @@ -276,9 +286,18 @@ decl_module! {
Ok(Some(base_weight + weight).into())
}
}

}

/// A pallet identifier. These are per pallet and should be stored in a registry somewhere.
#[derive(Clone, Copy, Eq, PartialEq, Encode, Decode)]
struct IndexedUtilityPalletId(u16);

impl TypeId for IndexedUtilityPalletId {
const TYPE_ID: [u8; 4] = *b"suba";
}

impl<T: Config> Module<T> {
impl<T: Config> Pallet<T> {
/// Derive a derivative account ID from the owner account and the sub-account index.
pub fn derivative_account_id(who: T::AccountId, index: u16) -> T::AccountId {
let entropy = (b"modlpy/utilisuba", who, index).using_encoded(blake2_256);
Expand Down
5 changes: 3 additions & 2 deletions frame/utility/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
use super::*;

use frame_support::{
assert_ok, assert_noop, parameter_types, assert_err_ignore_postinfo,
assert_ok, assert_noop, parameter_types, assert_err_ignore_postinfo, decl_module,
weights::{Weight, Pays},
dispatch::{DispatchError, DispatchErrorWithPostInfo, Dispatchable},
traits::Filter,
Expand All @@ -35,7 +35,8 @@ use crate as utility;
// example module to test behaviors.
pub mod example {
use super::*;
use frame_support::dispatch::WithPostDispatchInfo;
use frame_system::ensure_signed;
use frame_support::dispatch::{DispatchResultWithPostInfo, WithPostDispatchInfo};
pub trait Config: frame_system::Config { }

decl_module! {
Expand Down

0 comments on commit aa82655

Please sign in to comment.