mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 14:37:57 +00:00
ac3f14d23b
`polkadot-sdk` version of original tasks PR located here: https://github.com/paritytech/substrate/pull/14329 Fixes #206 ## Status - [x] Generic `Task` trait - [x] `RuntimeTask` aggregated enum, compatible with `construct_runtime!` - [x] Casting between `Task` and `RuntimeTask` without needing `dyn` or `Box` - [x] Tasks Example pallet - [x] Runtime tests for Tasks example pallet - [x] Parsing for task-related macros - [x] Retrofit parsing to make macros optional - [x] Expansion for task-related macros - [x] Adds support for args in tasks - [x] Retrofit tasks example pallet to use macros instead of manual syntax - [x] Weights - [x] Cleanup - [x] UI tests - [x] Docs ## Target Syntax Adapted from https://github.com/paritytech/polkadot-sdk/issues/206#issue-1865172283 ```rust // NOTE: this enum is optional and is auto-generated by the other macros if not present #[pallet::task] pub enum Task<T: Config> { AddNumberIntoTotal { i: u32, } } /// Some running total. #[pallet::storage] pub(super) type Total<T: Config<I>, I: 'static = ()> = StorageValue<_, (u32, u32), ValueQuery>; /// Numbers to be added into the total. #[pallet::storage] pub(super) type Numbers<T: Config<I>, I: 'static = ()> = StorageMap<_, Twox64Concat, u32, u32, OptionQuery>; #[pallet::tasks_experimental] impl<T: Config<I>, I: 'static> Pallet<T, I> { /// Add a pair of numbers into the totals and remove them. #[pallet::task_list(Numbers::<T, I>::iter_keys())] #[pallet::task_condition(|i| Numbers::<T, I>::contains_key(i))] #[pallet::task_index(0)] pub fn add_number_into_total(i: u32) -> DispatchResult { let v = Numbers::<T, I>::take(i).ok_or(Error::<T, I>::NotFound)?; Total::<T, I>::mutate(|(total_keys, total_values)| { *total_keys += i; *total_values += v; }); Ok(()) } } ``` --------- Co-authored-by: Nikhil Gupta <17176722+gupnik@users.noreply.github.com> Co-authored-by: kianenigma <kian@parity.io> Co-authored-by: Nikhil Gupta <> Co-authored-by: Gavin Wood <gavin@parity.io> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: gupnik <nikhilgupta.iitk@gmail.com>
236 lines
8.8 KiB
Rust
236 lines
8.8 KiB
Rust
// This file is part of Substrate.
|
|
|
|
// Copyright (C) Parity Technologies (UK) Ltd.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
//! # Default Config Pallet Example
|
|
//!
|
|
//! A simple example of a FRAME pallet that utilizes [`frame_support::derive_impl`] to demonstrate
|
|
//! the simpler way to implement `Config` trait of pallets. This example only showcases this in a
|
|
//! `mock.rs` environment, but the same applies to a real runtime as well.
|
|
//!
|
|
//! See the source code of [`tests`] for a real examples.
|
|
//!
|
|
//! Study the following types:
|
|
//!
|
|
//! - [`pallet::DefaultConfig`], and how it differs from [`pallet::Config`].
|
|
//! - [`struct@pallet::config_preludes::TestDefaultConfig`] and how it implements
|
|
//! [`pallet::DefaultConfig`].
|
|
//! - Notice how [`pallet::DefaultConfig`] is independent of [`frame_system::Config`].
|
|
|
|
#![cfg_attr(not(feature = "std"), no_std)]
|
|
|
|
#[frame_support::pallet]
|
|
pub mod pallet {
|
|
use frame_support::pallet_prelude::*;
|
|
|
|
/// This pallet is annotated to have a default config. This will auto-generate
|
|
/// [`DefaultConfig`].
|
|
///
|
|
/// It will be an identical, but won't have anything that is `#[pallet::no_default]`.
|
|
#[pallet::config(with_default)]
|
|
pub trait Config: frame_system::Config {
|
|
/// The overarching event type. This is coming from the runtime, and cannot have a default.
|
|
/// In general, `Runtime*`-oriented types cannot have a sensible default.
|
|
#[pallet::no_default] // optional. `RuntimeEvent` is automatically excluded as well.
|
|
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
|
|
|
|
/// The overarching task type.
|
|
#[pallet::no_default]
|
|
type RuntimeTask: Task;
|
|
|
|
/// An input parameter to this pallet. This value can have a default, because it is not
|
|
/// reliant on `frame_system::Config` or the overarching runtime in any way.
|
|
type WithDefaultValue: Get<u32>;
|
|
|
|
/// Same as [`Config::WithDefaultValue`], but we don't intend to define a default for this
|
|
/// in our tests below.
|
|
type OverwrittenDefaultValue: Get<u32>;
|
|
|
|
/// An input parameter that relies on `<Self as frame_system::Config>::AccountId`. This can
|
|
/// too have a default, as long as as it is present in `frame_system::DefaultConfig`.
|
|
type CanDeriveDefaultFromSystem: Get<Self::AccountId>;
|
|
|
|
/// We might chose to declare as one that doesn't have a default, for whatever semantical
|
|
/// reason.
|
|
#[pallet::no_default]
|
|
type HasNoDefault: Get<u32>;
|
|
|
|
/// Some types can technically have no default, such as those the rely on
|
|
/// `frame_system::Config` but are not present in `frame_system::DefaultConfig`. For
|
|
/// example, a `RuntimeCall` cannot reasonably have a default.
|
|
#[pallet::no_default] // if we skip this, there will be a compiler error.
|
|
type CannotHaveDefault: Get<Self::RuntimeCall>;
|
|
|
|
/// Something that is a normal type, with default.
|
|
type WithDefaultType;
|
|
|
|
/// Same as [`Config::WithDefaultType`], but we don't intend to define a default for this
|
|
/// in our tests below.
|
|
type OverwrittenDefaultType;
|
|
}
|
|
|
|
/// Container for different types that implement [`DefaultConfig`]` of this pallet.
|
|
pub mod config_preludes {
|
|
// This will help use not need to disambiguate anything when using `derive_impl`.
|
|
use super::*;
|
|
use frame_support::derive_impl;
|
|
use frame_system::config_preludes::TestDefaultConfig as SystemTestDefaultConfig;
|
|
|
|
/// A type providing default configurations for this pallet in testing environment.
|
|
pub struct TestDefaultConfig;
|
|
|
|
#[derive_impl(SystemTestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)]
|
|
impl frame_system::DefaultConfig for TestDefaultConfig {}
|
|
|
|
#[frame_support::register_default_impl(TestDefaultConfig)]
|
|
impl DefaultConfig for TestDefaultConfig {
|
|
type WithDefaultValue = frame_support::traits::ConstU32<42>;
|
|
type OverwrittenDefaultValue = frame_support::traits::ConstU32<42>;
|
|
|
|
// `frame_system::config_preludes::TestDefaultConfig` declares account-id as u64.
|
|
type CanDeriveDefaultFromSystem = frame_support::traits::ConstU64<42>;
|
|
|
|
type WithDefaultType = u32;
|
|
type OverwrittenDefaultType = u32;
|
|
}
|
|
|
|
/// A type providing default configurations for this pallet in another environment. Examples
|
|
/// could be a parachain, or a solo-chain.
|
|
///
|
|
/// Appropriate derive for `frame_system::DefaultConfig` needs to be provided. In this
|
|
/// example, we simple derive `frame_system::config_preludes::TestDefaultConfig` again.
|
|
pub struct OtherDefaultConfig;
|
|
|
|
#[derive_impl(SystemTestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)]
|
|
impl frame_system::DefaultConfig for OtherDefaultConfig {}
|
|
|
|
#[frame_support::register_default_impl(OtherDefaultConfig)]
|
|
impl DefaultConfig for OtherDefaultConfig {
|
|
type WithDefaultValue = frame_support::traits::ConstU32<66>;
|
|
type OverwrittenDefaultValue = frame_support::traits::ConstU32<66>;
|
|
type CanDeriveDefaultFromSystem = frame_support::traits::ConstU64<42>;
|
|
type WithDefaultType = u32;
|
|
type OverwrittenDefaultType = u32;
|
|
}
|
|
}
|
|
|
|
#[pallet::pallet]
|
|
pub struct Pallet<T>(_);
|
|
|
|
#[pallet::event]
|
|
pub enum Event<T: Config> {}
|
|
}
|
|
|
|
#[cfg(any(test, doc))]
|
|
pub mod tests {
|
|
use super::*;
|
|
use frame_support::{derive_impl, parameter_types};
|
|
use pallet::{self as pallet_default_config_example, config_preludes::*};
|
|
|
|
type Block = frame_system::mocking::MockBlock<Runtime>;
|
|
|
|
frame_support::construct_runtime!(
|
|
pub struct Runtime {
|
|
System: frame_system,
|
|
DefaultPallet: pallet_default_config_example,
|
|
}
|
|
);
|
|
|
|
#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
|
|
impl frame_system::Config for Runtime {
|
|
// these items are defined by frame-system as `no_default`, so we must specify them here.
|
|
type Block = Block;
|
|
|
|
// all of this is coming from `frame_system::config_preludes::TestDefaultConfig`.
|
|
|
|
// type Nonce = u32;
|
|
// type BlockNumber = u32;
|
|
// type Hash = sp_core::hash::H256;
|
|
// type Hashing = sp_runtime::traits::BlakeTwo256;
|
|
// type AccountId = u64;
|
|
// type Lookup = sp_runtime::traits::IdentityLookup<u64>;
|
|
// type BlockHashCount = frame_support::traits::ConstU32<10>;
|
|
// type MaxConsumers = frame_support::traits::ConstU32<16>;
|
|
// type AccountData = ();
|
|
// type OnNewAccount = ();
|
|
// type OnKilledAccount = ();
|
|
// type SystemWeightInfo = ();
|
|
// type SS58Prefix = ();
|
|
// type Version = ();
|
|
// type BlockWeights = ();
|
|
// type BlockLength = ();
|
|
// type DbWeight = ();
|
|
// type BaseCallFilter = frame_support::traits::Everything;
|
|
// type BlockHashCount = frame_support::traits::ConstU64<10>;
|
|
// type OnSetCode = ();
|
|
|
|
// These are marked as `#[inject_runtime_type]`. Hence, they are being injected as
|
|
// types generated by `construct_runtime`.
|
|
|
|
// type RuntimeOrigin = RuntimeOrigin;
|
|
// type RuntimeCall = RuntimeCall;
|
|
// type RuntimeEvent = RuntimeEvent;
|
|
// type PalletInfo = PalletInfo;
|
|
|
|
// you could still overwrite any of them if desired.
|
|
type SS58Prefix = frame_support::traits::ConstU16<456>;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const SomeCall: RuntimeCall = RuntimeCall::System(frame_system::Call::<Runtime>::remark { remark: vec![] });
|
|
}
|
|
|
|
#[derive_impl(TestDefaultConfig as pallet::DefaultConfig)]
|
|
impl pallet_default_config_example::Config for Runtime {
|
|
// These two both cannot have defaults.
|
|
type RuntimeEvent = RuntimeEvent;
|
|
type RuntimeTask = RuntimeTask;
|
|
|
|
type HasNoDefault = frame_support::traits::ConstU32<1>;
|
|
type CannotHaveDefault = SomeCall;
|
|
|
|
type OverwrittenDefaultValue = frame_support::traits::ConstU32<678>;
|
|
type OverwrittenDefaultType = u128;
|
|
}
|
|
|
|
#[test]
|
|
fn it_works() {
|
|
use frame_support::traits::Get;
|
|
use pallet::{Config, DefaultConfig};
|
|
|
|
// assert one of the value types that is not overwritten.
|
|
assert_eq!(
|
|
<<Runtime as Config>::WithDefaultValue as Get<u32>>::get(),
|
|
<<TestDefaultConfig as DefaultConfig>::WithDefaultValue as Get<u32>>::get()
|
|
);
|
|
|
|
// assert one of the value types that is overwritten.
|
|
assert_eq!(<<Runtime as Config>::OverwrittenDefaultValue as Get<u32>>::get(), 678u32);
|
|
|
|
// assert one of the types that is not overwritten.
|
|
assert_eq!(
|
|
std::any::TypeId::of::<<Runtime as Config>::WithDefaultType>(),
|
|
std::any::TypeId::of::<<TestDefaultConfig as DefaultConfig>::WithDefaultType>()
|
|
);
|
|
|
|
// assert one of the types that is overwritten.
|
|
assert_eq!(
|
|
std::any::TypeId::of::<<Runtime as Config>::OverwrittenDefaultType>(),
|
|
std::any::TypeId::of::<u128>()
|
|
)
|
|
}
|
|
}
|