Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Migrate pallet-utility to pallet attribute macro. #8326

Merged
4 commits merged into from
Mar 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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