diff --git a/Cargo.lock b/Cargo.lock index 2fff57879891..5c24e6c20d15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18514,6 +18514,21 @@ version = "0.12.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" +[[package]] +name = "tasks-example" +version = "4.0.0-dev" +dependencies = [ + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "tempfile" version = "3.8.0" diff --git a/Cargo.toml b/Cargo.toml index 4db27b98e907..35d4809ade09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -294,6 +294,7 @@ members = [ "substrate/frame/examples/kitchensink", "substrate/frame/examples/offchain-worker", "substrate/frame/examples/split", + "substrate/frame/examples/tasks-example", "substrate/frame/executive", "substrate/frame/fast-unstake", "substrate/frame/glutton", diff --git a/substrate/bin/node-template/pallets/template/src/mock.rs b/substrate/bin/node-template/pallets/template/src/mock.rs index 244ae1b37859..39c58d03efac 100644 --- a/substrate/bin/node-template/pallets/template/src/mock.rs +++ b/substrate/bin/node-template/pallets/template/src/mock.rs @@ -24,6 +24,7 @@ impl frame_system::Config for Test { type DbWeight = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = u64; type Hash = H256; type Hashing = BlakeTwo256; diff --git a/substrate/bin/node-template/runtime/src/lib.rs b/substrate/bin/node-template/runtime/src/lib.rs index 216be9588bca..249841e546b9 100644 --- a/substrate/bin/node-template/runtime/src/lib.rs +++ b/substrate/bin/node-template/runtime/src/lib.rs @@ -165,6 +165,8 @@ impl frame_system::Config for Runtime { type AccountId = AccountId; /// The aggregated dispatch type that is available for extrinsics. type RuntimeCall = RuntimeCall; + /// The aggregated task type that is available for extrinsics. + type RuntimeTask = RuntimeTask; /// The lookup mechanism to get account ID from whatever is passed in dispatchers. type Lookup = AccountIdLookup; /// The type for storing how many extrinsics an account has signed. @@ -243,6 +245,7 @@ impl pallet_balances::Config for Runtime { type Balance = Balance; /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type DustRemoval = (); type ExistentialDeposit = ConstU128; type AccountStore = System; diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 4f34e4ecd812..0558798de572 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -87,6 +87,7 @@ use sp_std::prelude::*; use sp_version::NativeVersion; use sp_version::RuntimeVersion; use static_assertions::const_assert; +use tasks_example; #[cfg(any(feature = "std", test))] pub use frame_system::Call as SystemCall; @@ -287,6 +288,7 @@ impl frame_system::Config for Runtime { type DbWeight = RocksDbWeight; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = Nonce; type Hash = Hash; type Hashing = BlakeTwo256; @@ -308,6 +310,11 @@ impl frame_system::Config for Runtime { impl pallet_insecure_randomness_collective_flip::Config for Runtime {} +impl tasks_example::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; +} + impl pallet_utility::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; @@ -512,6 +519,7 @@ impl pallet_balances::Config for Runtime { type Balance = Balance; type DustRemoval = (); type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type ExistentialDeposit = ExistentialDeposit; type AccountStore = frame_system::Pallet; type WeightInfo = pallet_balances::weights::SubstrateWeight; @@ -2171,6 +2179,7 @@ mod benches { [pallet_conviction_voting, ConvictionVoting] [pallet_contracts, Contracts] [pallet_core_fellowship, CoreFellowship] + [tasks_example, TasksExample] [pallet_democracy, Democracy] [pallet_asset_conversion, AssetConversion] [pallet_election_provider_multi_phase, ElectionProviderMultiPhase] diff --git a/substrate/frame/alliance/src/mock.rs b/substrate/frame/alliance/src/mock.rs index f04e7e414ed9..cfd47e60a3e8 100644 --- a/substrate/frame/alliance/src/mock.rs +++ b/substrate/frame/alliance/src/mock.rs @@ -51,6 +51,7 @@ impl frame_system::Config for Test { type BlockLength = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = u64; type Hash = H256; type Hashing = BlakeTwo256; @@ -79,6 +80,7 @@ impl pallet_balances::Config for Test { type Balance = u64; type DustRemoval = (); type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = (); diff --git a/substrate/frame/asset-conversion/src/mock.rs b/substrate/frame/asset-conversion/src/mock.rs index 3a19f39e7ca6..faf7d769a167 100644 --- a/substrate/frame/asset-conversion/src/mock.rs +++ b/substrate/frame/asset-conversion/src/mock.rs @@ -54,6 +54,7 @@ impl frame_system::Config for Test { type BlockLength = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = u64; type Hash = H256; type Hashing = BlakeTwo256; @@ -88,6 +89,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } impl pallet_assets::Config for Test { diff --git a/substrate/frame/asset-rate/src/mock.rs b/substrate/frame/asset-rate/src/mock.rs index 5fe0d4240af5..38c92d80ed59 100644 --- a/substrate/frame/asset-rate/src/mock.rs +++ b/substrate/frame/asset-rate/src/mock.rs @@ -42,6 +42,7 @@ impl frame_system::Config for Test { type BlockLength = (); type DbWeight = (); type RuntimeOrigin = RuntimeOrigin; + type RuntimeTask = RuntimeTask; type RuntimeCall = RuntimeCall; type Nonce = u64; type Hash = H256; @@ -76,6 +77,7 @@ impl pallet_balances::Config for Test { type FreezeIdentifier = (); type MaxHolds = (); type MaxFreezes = (); + type RuntimeTask = RuntimeTask; } impl pallet_asset_rate::Config for Test { diff --git a/substrate/frame/assets/src/mock.rs b/substrate/frame/assets/src/mock.rs index 32ad02da9041..d7ab85c4eb20 100644 --- a/substrate/frame/assets/src/mock.rs +++ b/substrate/frame/assets/src/mock.rs @@ -52,6 +52,7 @@ impl frame_system::Config for Test { type BlockLength = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = u64; type Hash = H256; type Hashing = BlakeTwo256; @@ -86,6 +87,7 @@ impl pallet_balances::Config for Test { type FreezeIdentifier = (); type MaxHolds = (); type MaxFreezes = (); + type RuntimeTask = RuntimeTask; } pub struct AssetsCallbackHandle; diff --git a/substrate/frame/atomic-swap/src/tests.rs b/substrate/frame/atomic-swap/src/tests.rs index e20e1df564c7..493727570860 100644 --- a/substrate/frame/atomic-swap/src/tests.rs +++ b/substrate/frame/atomic-swap/src/tests.rs @@ -47,6 +47,7 @@ impl frame_system::Config for Test { type Nonce = u64; type Hash = H256; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; @@ -78,6 +79,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } impl Config for Test { diff --git a/substrate/frame/aura/src/mock.rs b/substrate/frame/aura/src/mock.rs index 39b798c2f684..fe3479e34f22 100644 --- a/substrate/frame/aura/src/mock.rs +++ b/substrate/frame/aura/src/mock.rs @@ -49,6 +49,7 @@ impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = ::sp_runtime::traits::BlakeTwo256; type AccountId = u64; diff --git a/substrate/frame/authority-discovery/src/lib.rs b/substrate/frame/authority-discovery/src/lib.rs index 87b743ae1967..0e6150f3d65f 100644 --- a/substrate/frame/authority-discovery/src/lib.rs +++ b/substrate/frame/authority-discovery/src/lib.rs @@ -233,6 +233,7 @@ mod tests { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = ::sp_runtime::traits::BlakeTwo256; type AccountId = AuthorityId; diff --git a/substrate/frame/authorship/src/lib.rs b/substrate/frame/authorship/src/lib.rs index a9bd0c38cb67..a434b0956afe 100644 --- a/substrate/frame/authorship/src/lib.rs +++ b/substrate/frame/authorship/src/lib.rs @@ -143,6 +143,7 @@ mod tests { type SS58Prefix = (); type OnSetCode = (); type MaxConsumers = ConstU32<16>; + type RuntimeTask = RuntimeTask; } impl pallet::Config for Test { diff --git a/substrate/frame/babe/src/mock.rs b/substrate/frame/babe/src/mock.rs index dbffe9f312e6..85143f9e5709 100644 --- a/substrate/frame/babe/src/mock.rs +++ b/substrate/frame/babe/src/mock.rs @@ -71,6 +71,7 @@ impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Version = (); type Hashing = sp_runtime::traits::BlakeTwo256; @@ -139,6 +140,7 @@ impl pallet_balances::Config for Test { type Balance = u128; type DustRemoval = (); type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type ExistentialDeposit = ConstU128<1>; type AccountStore = System; type WeightInfo = (); diff --git a/substrate/frame/bags-list/src/mock.rs b/substrate/frame/bags-list/src/mock.rs index ae50adabd508..a6226b6f0324 100644 --- a/substrate/frame/bags-list/src/mock.rs +++ b/substrate/frame/bags-list/src/mock.rs @@ -54,6 +54,7 @@ impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = sp_core::H256; type Hashing = sp_runtime::traits::BlakeTwo256; type AccountId = AccountId; diff --git a/substrate/frame/balances/src/lib.rs b/substrate/frame/balances/src/lib.rs index 5da6600d8796..f5be4b4456c3 100644 --- a/substrate/frame/balances/src/lib.rs +++ b/substrate/frame/balances/src/lib.rs @@ -249,6 +249,10 @@ pub mod pallet { type RuntimeEvent: From> + IsType<::RuntimeEvent>; + /// The overarching task type. + #[pallet::no_default] + type RuntimeTask: AggregatedTask; + /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; diff --git a/substrate/frame/balances/src/tests/mod.rs b/substrate/frame/balances/src/tests/mod.rs index d15f8e89118c..acfbc4e453b0 100644 --- a/substrate/frame/balances/src/tests/mod.rs +++ b/substrate/frame/balances/src/tests/mod.rs @@ -94,6 +94,7 @@ impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = ::sp_runtime::traits::BlakeTwo256; type AccountId = u64; @@ -135,6 +136,7 @@ impl Config for Test { type FreezeIdentifier = TestId; type MaxFreezes = ConstU32<2>; type MaxHolds = ConstU32<2>; + type RuntimeTask = RuntimeTask; } #[derive(Clone)] diff --git a/substrate/frame/beefy-mmr/src/mock.rs b/substrate/frame/beefy-mmr/src/mock.rs index b2d8758a04be..441771723ad6 100644 --- a/substrate/frame/beefy-mmr/src/mock.rs +++ b/substrate/frame/beefy-mmr/src/mock.rs @@ -67,6 +67,7 @@ impl frame_system::Config for Test { type Nonce = u64; type Hash = H256; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; diff --git a/substrate/frame/beefy/src/mock.rs b/substrate/frame/beefy/src/mock.rs index b55a65dbd73a..fa440bad8d90 100644 --- a/substrate/frame/beefy/src/mock.rs +++ b/substrate/frame/beefy/src/mock.rs @@ -78,6 +78,7 @@ impl frame_system::Config for Test { type Nonce = u64; type Hash = H256; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; @@ -155,6 +156,7 @@ impl pallet_balances::Config for Test { type Balance = u128; type DustRemoval = (); type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type ExistentialDeposit = ConstU128<1>; type AccountStore = System; type WeightInfo = (); diff --git a/substrate/frame/benchmarking/pov/src/tests.rs b/substrate/frame/benchmarking/pov/src/tests.rs index f09e37a5288a..94aea232c6cf 100644 --- a/substrate/frame/benchmarking/pov/src/tests.rs +++ b/substrate/frame/benchmarking/pov/src/tests.rs @@ -182,6 +182,7 @@ mod mock { type RuntimeOrigin = RuntimeOrigin; type Nonce = u32; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = ::sp_runtime::traits::BlakeTwo256; type AccountId = u32; diff --git a/substrate/frame/benchmarking/src/tests.rs b/substrate/frame/benchmarking/src/tests.rs index e5bacbdb2361..43b48476ed3a 100644 --- a/substrate/frame/benchmarking/src/tests.rs +++ b/substrate/frame/benchmarking/src/tests.rs @@ -84,6 +84,7 @@ impl frame_system::Config for Test { type Nonce = u64; type Hash = H256; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; diff --git a/substrate/frame/benchmarking/src/tests_instance.rs b/substrate/frame/benchmarking/src/tests_instance.rs index f2c721c8114c..ca8b56e8c902 100644 --- a/substrate/frame/benchmarking/src/tests_instance.rs +++ b/substrate/frame/benchmarking/src/tests_instance.rs @@ -91,6 +91,7 @@ impl frame_system::Config for Test { type BlockLength = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = u64; type Hash = H256; type Hashing = BlakeTwo256; diff --git a/substrate/frame/bounties/src/tests.rs b/substrate/frame/bounties/src/tests.rs index a6fb89bb8601..6b32278f3ab4 100644 --- a/substrate/frame/bounties/src/tests.rs +++ b/substrate/frame/bounties/src/tests.rs @@ -64,6 +64,7 @@ impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = u128; // u64 is not enough to hold bytes used to generate bounty account @@ -88,6 +89,7 @@ impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type Balance = Balance; type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type DustRemoval = (); type ExistentialDeposit = ConstU64<1>; type AccountStore = System; diff --git a/substrate/frame/broker/src/mock.rs b/substrate/frame/broker/src/mock.rs index cab6b7389c06..cfd3368d5f1e 100644 --- a/substrate/frame/broker/src/mock.rs +++ b/substrate/frame/broker/src/mock.rs @@ -54,6 +54,7 @@ impl frame_system::Config for Test { type DbWeight = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = u64; type Hash = H256; type Hashing = BlakeTwo256; diff --git a/substrate/frame/child-bounties/src/tests.rs b/substrate/frame/child-bounties/src/tests.rs index 24a6410f29f7..52ff3e6b8116 100644 --- a/substrate/frame/child-bounties/src/tests.rs +++ b/substrate/frame/child-bounties/src/tests.rs @@ -67,6 +67,7 @@ impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = u128; @@ -91,6 +92,7 @@ impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type Balance = Balance; type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type DustRemoval = (); type ExistentialDeposit = ConstU64<1>; type AccountStore = System; diff --git a/substrate/frame/collective/src/tests.rs b/substrate/frame/collective/src/tests.rs index 86b85e07a8bd..0e89ab01bdce 100644 --- a/substrate/frame/collective/src/tests.rs +++ b/substrate/frame/collective/src/tests.rs @@ -114,6 +114,7 @@ impl frame_system::Config for Test { type SS58Prefix = (); type OnSetCode = (); type MaxConsumers = ConstU32<16>; + type RuntimeTask = RuntimeTask; } impl Config for Test { type RuntimeOrigin = RuntimeOrigin; diff --git a/substrate/frame/contracts/src/tests.rs b/substrate/frame/contracts/src/tests.rs index 8d6c5c5ac728..8dcb0e8cc4a5 100644 --- a/substrate/frame/contracts/src/tests.rs +++ b/substrate/frame/contracts/src/tests.rs @@ -340,6 +340,7 @@ impl frame_system::Config for Test { type Nonce = u64; type Hash = H256; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hashing = BlakeTwo256; type AccountId = AccountId32; type Lookup = IdentityLookup; @@ -363,6 +364,7 @@ impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type Balance = u64; type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; diff --git a/substrate/frame/conviction-voting/src/tests.rs b/substrate/frame/conviction-voting/src/tests.rs index 656112deebfb..8558b376225b 100644 --- a/substrate/frame/conviction-voting/src/tests.rs +++ b/substrate/frame/conviction-voting/src/tests.rs @@ -59,6 +59,7 @@ impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = u64; @@ -83,6 +84,7 @@ impl pallet_balances::Config for Test { type MaxLocks = ConstU32<10>; type Balance = u64; type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type DustRemoval = (); type ExistentialDeposit = ConstU64<1>; type AccountStore = System; diff --git a/substrate/frame/core-fellowship/src/tests.rs b/substrate/frame/core-fellowship/src/tests.rs index a02c010718c9..25c547a34270 100644 --- a/substrate/frame/core-fellowship/src/tests.rs +++ b/substrate/frame/core-fellowship/src/tests.rs @@ -74,6 +74,7 @@ impl frame_system::Config for Test { type SS58Prefix = (); type OnSetCode = (); type MaxConsumers = ConstU32<16>; + type RuntimeTask = RuntimeTask; } thread_local! { diff --git a/substrate/frame/democracy/src/tests.rs b/substrate/frame/democracy/src/tests.rs index e5cfcc5b4002..eaeeb47f34ed 100644 --- a/substrate/frame/democracy/src/tests.rs +++ b/substrate/frame/democracy/src/tests.rs @@ -85,6 +85,7 @@ impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = u64; @@ -134,6 +135,7 @@ impl pallet_balances::Config for Test { type MaxLocks = ConstU32<10>; type Balance = u64; type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type DustRemoval = (); type ExistentialDeposit = ConstU64<1>; type AccountStore = System; diff --git a/substrate/frame/election-provider-multi-phase/src/mock.rs b/substrate/frame/election-provider-multi-phase/src/mock.rs index 05d151e51ecc..56b30ff9622b 100644 --- a/substrate/frame/election-provider-multi-phase/src/mock.rs +++ b/substrate/frame/election-provider-multi-phase/src/mock.rs @@ -210,6 +210,7 @@ impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = AccountId; @@ -254,6 +255,7 @@ impl pallet_balances::Config for Runtime { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } #[derive(Default, Eq, PartialEq, Debug, Clone, Copy)] diff --git a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs index 501f9f89ab7a..f25b7163413b 100644 --- a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs +++ b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs @@ -92,6 +92,7 @@ impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type RuntimeEvent = RuntimeEvent; type PalletInfo = PalletInfo; type OnSetCode = (); @@ -115,6 +116,7 @@ impl pallet_balances::Config for Runtime { type ReserveIdentifier = [u8; 8]; type Balance = Balance; type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; diff --git a/substrate/frame/election-provider-support/src/onchain.rs b/substrate/frame/election-provider-support/src/onchain.rs index 8ac245a360bb..fa875261f201 100644 --- a/substrate/frame/election-provider-support/src/onchain.rs +++ b/substrate/frame/election-provider-support/src/onchain.rs @@ -206,6 +206,7 @@ mod tests { type RuntimeOrigin = RuntimeOrigin; type Nonce = Nonce; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = sp_core::H256; type Hashing = sp_runtime::traits::BlakeTwo256; type AccountId = AccountId; diff --git a/substrate/frame/elections-phragmen/src/lib.rs b/substrate/frame/elections-phragmen/src/lib.rs index 6912649bd122..2622e32ee145 100644 --- a/substrate/frame/elections-phragmen/src/lib.rs +++ b/substrate/frame/elections-phragmen/src/lib.rs @@ -1326,6 +1326,7 @@ mod tests { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = u64; @@ -1347,6 +1348,7 @@ mod tests { impl pallet_balances::Config for Test { type Balance = u64; type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type DustRemoval = (); type ExistentialDeposit = ConstU64<1>; type AccountStore = frame_system::Pallet; diff --git a/substrate/frame/examples/basic/src/tests.rs b/substrate/frame/examples/basic/src/tests.rs index addf219dc3c3..3b21ce98b18a 100644 --- a/substrate/frame/examples/basic/src/tests.rs +++ b/substrate/frame/examples/basic/src/tests.rs @@ -53,6 +53,7 @@ impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type Hash = H256; + type RuntimeTask = RuntimeTask; type RuntimeCall = RuntimeCall; type Hashing = BlakeTwo256; type AccountId = u64; @@ -85,6 +86,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } impl Config for Test { diff --git a/substrate/frame/examples/default-config/src/lib.rs b/substrate/frame/examples/default-config/src/lib.rs index d2eade0ccff1..15096e53e4e3 100644 --- a/substrate/frame/examples/default-config/src/lib.rs +++ b/substrate/frame/examples/default-config/src/lib.rs @@ -47,6 +47,9 @@ pub mod pallet { #[pallet::no_default] // optional. `RuntimeEvent` is automatically excluded as well. type RuntimeEvent: From> + IsType<::RuntimeEvent>; + #[pallet::no_default] + type RuntimeTask: AggregatedTask; + /// 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; @@ -198,6 +201,7 @@ pub mod tests { type OverwrittenDefaultValue = frame_support::traits::ConstU32<678>; type OverwrittenDefaultType = u128; + type RuntimeTask = RuntimeTask; } #[test] diff --git a/substrate/frame/examples/dev-mode/src/tests.rs b/substrate/frame/examples/dev-mode/src/tests.rs index ba98f5174ce2..3ce72c858848 100644 --- a/substrate/frame/examples/dev-mode/src/tests.rs +++ b/substrate/frame/examples/dev-mode/src/tests.rs @@ -47,6 +47,7 @@ impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type Hash = H256; + type RuntimeTask = RuntimeTask; type RuntimeCall = RuntimeCall; type Hashing = BlakeTwo256; type AccountId = u64; @@ -79,6 +80,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = RuntimeHoldReason; type MaxHolds = (); + type RuntimeTask = RuntimeTask; } impl Config for Test { diff --git a/substrate/frame/examples/kitchensink/src/tests.rs b/substrate/frame/examples/kitchensink/src/tests.rs index b2af7c8983f5..da83fe846c15 100644 --- a/substrate/frame/examples/kitchensink/src/tests.rs +++ b/substrate/frame/examples/kitchensink/src/tests.rs @@ -43,6 +43,7 @@ impl frame_system::Config for Test { type Block = Block; type BlockHashCount = ConstU64<10>; type RuntimeOrigin = RuntimeOrigin; + type RuntimeTask = RuntimeTask; type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; type PalletInfo = PalletInfo; @@ -65,6 +66,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } parameter_types! { diff --git a/substrate/frame/examples/offchain-worker/src/tests.rs b/substrate/frame/examples/offchain-worker/src/tests.rs index 203a59a8af03..38e9a48701b2 100644 --- a/substrate/frame/examples/offchain-worker/src/tests.rs +++ b/substrate/frame/examples/offchain-worker/src/tests.rs @@ -53,6 +53,7 @@ impl frame_system::Config for Test { type DbWeight = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = u64; type Hash = H256; type Hashing = BlakeTwo256; diff --git a/substrate/frame/examples/tasks-example/Cargo.toml b/substrate/frame/examples/tasks-example/Cargo.toml new file mode 100644 index 000000000000..d90de4fae960 --- /dev/null +++ b/substrate/frame/examples/tasks-example/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "tasks-example" +version = "4.0.0-dev" +authors = ["Parity Technologies "] +edition = "2021" +license = "MIT-0" +homepage = "https://substrate.io" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME example pallet" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } +log = { version = "0.4.17", default-features = false } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" } +frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" } +sp-io = { version = "23.0.0", default-features = false, path = "../../../primitives/io" } +sp-runtime = { version = "24.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-std = { version = "8.0.0", default-features = false, path = "../../../primitives/std" } +sp-core = { version = "21.0.0", default-features = false, path = "../../../primitives/core" } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-support/std", + "frame-system/std", + "log/std", + "scale-info/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", + "sp-core/std", +] +try-runtime = ["frame-support/try-runtime"] diff --git a/substrate/frame/examples/tasks-example/src/lib.rs b/substrate/frame/examples/tasks-example/src/lib.rs new file mode 100644 index 000000000000..2223ecbd0d30 --- /dev/null +++ b/substrate/frame/examples/tasks-example/src/lib.rs @@ -0,0 +1,179 @@ +// 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. + +#![cfg_attr(not(feature = "std"), no_std)] + +use core::marker::PhantomData; + +use codec::{Decode, Encode}; +use frame_support::dispatch::DispatchResult; +// Re-export pallet items so that they can be accessed from the crate namespace. +pub use pallet::*; +use sp_runtime::DispatchError; + +#[frame_support::pallet(dev_mode)] +pub mod pallet { + + use super::*; + use frame_support::{pallet_prelude::*, traits::AggregatedTask}; + use frame_system::pallet_prelude::*; + + // this can be auto-generated from the macros + #[derive(Clone, PartialEq, Eq, Encode, Decode, TypeInfo)] + pub enum Task { + Increment, + Decrement, + #[doc(hidden)] + #[codec(skip)] + __Ignore(PhantomData, frame_support::Never), + } + + // this can be auto-generated from the macros and will always be the same + impl core::fmt::Debug for Task { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("Task").field("value", self).finish() + } + } + + // we can automatically inject `InvalidTask` into an existing Error enum by finding it via + // visitor pattern, otherwise we can just emit an error enum containing just our + // `InvalidTask` variant. Alternatively we could just expect that `InvalidTask` is included + // in the error enum, by convention, or we could use something like + // `InvalidTransaction::Custom(1u8)` but this seems bad to me. + #[pallet::error] + pub enum Error { + InvalidTask, + ValueOverflow, + ValueUnderflow, + } + + // this will be auto-generated from `#[pallet::tasks]` + impl frame_support::traits::Task for Task + where + T: TypeInfo, + { + type Enumeration = sp_std::vec::IntoIter>; + + const TASK_INDEX: u64 = 0; + + fn enumerate() -> Self::Enumeration { + sp_std::vec![Task::Increment, Task::Decrement].into_iter() + } + + fn is_valid(&self) -> bool { + let value = Value::::get().unwrap(); + match self { + Task::Increment => value < 255, + Task::Decrement => value > 0, + Task::__Ignore(_, _) => unreachable!(), + } + } + + fn run(&self) -> Result<(), DispatchError> { + match self { + Task::Increment => { + // Get the value and check if it can be incremented + let value = Value::::get().unwrap_or_default(); + if value >= 255 { + Err(Error::::ValueOverflow.into()) + } else { + let new_val = value.checked_add(1).ok_or(Error::::ValueOverflow)?; + Value::::put(new_val); + Pallet::::deposit_event(Event::Incremented { new_val }); + Ok(()) + } + }, + Task::Decrement => { + // Get the value and check if it can be decremented + let value = Value::::get().unwrap_or_default(); + if value == 0 { + Err(Error::::ValueUnderflow.into()) + } else { + let new_val = value.checked_sub(1).ok_or(Error::::ValueUnderflow)?; + Value::::put(new_val); + Pallet::::deposit_event(Event::Decremented { new_val }); + Ok(()) + } + }, + Task::__Ignore(_, _) => unreachable!(), + } + } + + fn weight(&self) -> Weight { + Weight::default() + } + } + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + type RuntimeTask: AggregatedTask; + } + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn value)] + pub type Value = StorageValue<_, u8>; + + #[pallet::call] + impl Pallet + where + T: TypeInfo, + { + pub fn increment(origin: OriginFor) -> DispatchResult { + ensure_root(origin)?; + + // Increment the value and emit an event + let new_val = Value::::get().unwrap().checked_add(1).ok_or("Value overflow")?; + Value::::put(new_val); + Self::deposit_event(Event::Incremented { new_val }); + + Ok(()) + } + + pub fn decrement(origin: OriginFor) -> DispatchResult { + ensure_root(origin)?; + + // Decrement the value and emit an event + let new_val = Value::::get().unwrap().checked_sub(1).ok_or("Value underflow")?; + Value::::put(new_val); + Self::deposit_event(Event::Decremented { new_val }); + + Ok(()) + } + + // this will be auto-generated by the macros and will always be the same + pub fn do_task(origin: OriginFor, task: Task) -> DispatchResult { + use frame_support::traits::Task; + ensure_root(origin)?; + if task.is_valid() { + task.run() + } else { + Err(Error::::InvalidTask.into()) + } + } + } + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + Incremented { new_val: u8 }, + Decremented { new_val: u8 }, + } +} diff --git a/substrate/frame/executive/src/lib.rs b/substrate/frame/executive/src/lib.rs index 1d9afdfa60aa..f7d71be3e97b 100644 --- a/substrate/frame/executive/src/lib.rs +++ b/substrate/frame/executive/src/lib.rs @@ -872,6 +872,7 @@ mod tests { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = sp_core::H256; type Hashing = BlakeTwo256; type AccountId = u64; @@ -905,6 +906,7 @@ mod tests { type MaxFreezes = ConstU32<1>; type RuntimeHoldReason = (); type MaxHolds = ConstU32<1>; + type RuntimeTask = RuntimeTask; } parameter_types! { diff --git a/substrate/frame/fast-unstake/src/mock.rs b/substrate/frame/fast-unstake/src/mock.rs index dc24a823c0db..18a16be778e7 100644 --- a/substrate/frame/fast-unstake/src/mock.rs +++ b/substrate/frame/fast-unstake/src/mock.rs @@ -52,6 +52,7 @@ impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type Nonce = Nonce; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = sp_core::H256; type Hashing = sp_runtime::traits::BlakeTwo256; type AccountId = AccountId; @@ -87,6 +88,7 @@ impl pallet_balances::Config for Runtime { type ReserveIdentifier = [u8; 8]; type Balance = Balance; type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; diff --git a/substrate/frame/glutton/src/mock.rs b/substrate/frame/glutton/src/mock.rs index 4bc40b547887..90a7a59dca11 100644 --- a/substrate/frame/glutton/src/mock.rs +++ b/substrate/frame/glutton/src/mock.rs @@ -47,6 +47,7 @@ impl frame_system::Config for Test { type Nonce = u64; type Hash = H256; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; diff --git a/substrate/frame/grandpa/src/mock.rs b/substrate/frame/grandpa/src/mock.rs index fd4d737dc493..ce3df8f50dda 100644 --- a/substrate/frame/grandpa/src/mock.rs +++ b/substrate/frame/grandpa/src/mock.rs @@ -74,6 +74,7 @@ impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = sp_runtime::traits::BlakeTwo256; type AccountId = u64; @@ -135,6 +136,7 @@ impl pallet_balances::Config for Test { type Balance = u128; type DustRemoval = (); type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type ExistentialDeposit = ConstU128<1>; type AccountStore = System; type WeightInfo = (); diff --git a/substrate/frame/identity/src/tests.rs b/substrate/frame/identity/src/tests.rs index 1532980574c2..13de690e6768 100644 --- a/substrate/frame/identity/src/tests.rs +++ b/substrate/frame/identity/src/tests.rs @@ -52,6 +52,7 @@ impl frame_system::Config for Test { type Nonce = u64; type Hash = H256; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; @@ -84,6 +85,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } parameter_types! { diff --git a/substrate/frame/im-online/src/mock.rs b/substrate/frame/im-online/src/mock.rs index 85da061fe904..a9a1350076f2 100644 --- a/substrate/frame/im-online/src/mock.rs +++ b/substrate/frame/im-online/src/mock.rs @@ -121,6 +121,7 @@ impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = u64; diff --git a/substrate/frame/indices/src/mock.rs b/substrate/frame/indices/src/mock.rs index d63081e0b73f..7941b3291abf 100644 --- a/substrate/frame/indices/src/mock.rs +++ b/substrate/frame/indices/src/mock.rs @@ -42,6 +42,7 @@ impl frame_system::Config for Test { type DbWeight = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = u64; type Hash = H256; type Hashing = ::sp_runtime::traits::BlakeTwo256; @@ -75,6 +76,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } impl Config for Test { diff --git a/substrate/frame/insecure-randomness-collective-flip/src/lib.rs b/substrate/frame/insecure-randomness-collective-flip/src/lib.rs index 474087777c46..f7119f63a6f9 100644 --- a/substrate/frame/insecure-randomness-collective-flip/src/lib.rs +++ b/substrate/frame/insecure-randomness-collective-flip/src/lib.rs @@ -197,6 +197,7 @@ mod tests { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = u64; diff --git a/substrate/frame/lottery/src/mock.rs b/substrate/frame/lottery/src/mock.rs index aefb6a1cce2b..b462a5a736e6 100644 --- a/substrate/frame/lottery/src/mock.rs +++ b/substrate/frame/lottery/src/mock.rs @@ -55,6 +55,7 @@ impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = u64; @@ -79,6 +80,7 @@ impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type Balance = u64; type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type DustRemoval = (); type ExistentialDeposit = ConstU64<1>; type AccountStore = System; diff --git a/substrate/frame/membership/src/lib.rs b/substrate/frame/membership/src/lib.rs index 6fb61f0e491b..f2433a7d70ca 100644 --- a/substrate/frame/membership/src/lib.rs +++ b/substrate/frame/membership/src/lib.rs @@ -560,6 +560,7 @@ mod tests { type Nonce = u64; type Hash = H256; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; diff --git a/substrate/frame/merkle-mountain-range/src/mock.rs b/substrate/frame/merkle-mountain-range/src/mock.rs index ecc254278bf0..ff46c0c9c3cf 100644 --- a/substrate/frame/merkle-mountain-range/src/mock.rs +++ b/substrate/frame/merkle-mountain-range/src/mock.rs @@ -41,6 +41,7 @@ impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = u64; type Hash = H256; type Hashing = BlakeTwo256; diff --git a/substrate/frame/message-queue/src/integration_test.rs b/substrate/frame/message-queue/src/integration_test.rs index a1003edf3c92..20bc4412210b 100644 --- a/substrate/frame/message-queue/src/integration_test.rs +++ b/substrate/frame/message-queue/src/integration_test.rs @@ -59,6 +59,7 @@ impl frame_system::Config for Test { type Nonce = u64; type Hash = H256; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; diff --git a/substrate/frame/message-queue/src/mock.rs b/substrate/frame/message-queue/src/mock.rs index 473c5faac4c5..8ee0d9a0a6cc 100644 --- a/substrate/frame/message-queue/src/mock.rs +++ b/substrate/frame/message-queue/src/mock.rs @@ -52,6 +52,7 @@ impl frame_system::Config for Test { type Nonce = u64; type Hash = H256; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; diff --git a/substrate/frame/multisig/src/tests.rs b/substrate/frame/multisig/src/tests.rs index e7fc5b3e4aae..7dab8a10a758 100644 --- a/substrate/frame/multisig/src/tests.rs +++ b/substrate/frame/multisig/src/tests.rs @@ -44,6 +44,7 @@ impl frame_system::Config for Test { type Block = Block; type BlockHashCount = ConstU32<250>; type RuntimeOrigin = RuntimeOrigin; + type RuntimeTask = RuntimeTask; type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; type BaseCallFilter = TestBaseCallFilter; @@ -61,6 +62,7 @@ impl pallet_balances::Config for Test { type DustRemoval = (); type AccountStore = System; type ExistentialDeposit = ConstU64<1>; + type RuntimeTask = RuntimeTask; } pub struct TestBaseCallFilter; diff --git a/substrate/frame/nft-fractionalization/src/mock.rs b/substrate/frame/nft-fractionalization/src/mock.rs index c690f0e580ed..3b0b998fb16e 100644 --- a/substrate/frame/nft-fractionalization/src/mock.rs +++ b/substrate/frame/nft-fractionalization/src/mock.rs @@ -55,6 +55,7 @@ impl frame_system::Config for Test { type BlockLength = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = u64; type Hash = H256; type Hashing = BlakeTwo256; @@ -79,6 +80,7 @@ impl pallet_balances::Config for Test { type Balance = u64; type DustRemoval = (); type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); diff --git a/substrate/frame/nfts/src/mock.rs b/substrate/frame/nfts/src/mock.rs index f091a53f8d7c..cb4bba74dae4 100644 --- a/substrate/frame/nfts/src/mock.rs +++ b/substrate/frame/nfts/src/mock.rs @@ -52,6 +52,7 @@ impl frame_system::Config for Test { type BlockLength = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = u64; type Hash = H256; type Hashing = BlakeTwo256; @@ -86,6 +87,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } parameter_types! { diff --git a/substrate/frame/nicks/src/lib.rs b/substrate/frame/nicks/src/lib.rs index 0a68f7d7142d..36491752d550 100644 --- a/substrate/frame/nicks/src/lib.rs +++ b/substrate/frame/nicks/src/lib.rs @@ -282,6 +282,7 @@ mod tests { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type Hash = H256; + type RuntimeTask = RuntimeTask; type RuntimeCall = RuntimeCall; type Hashing = BlakeTwo256; type AccountId = u64; @@ -314,6 +315,7 @@ mod tests { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } ord_parameter_types! { diff --git a/substrate/frame/nis/src/mock.rs b/substrate/frame/nis/src/mock.rs index 76fdf5f3f069..65f41fc34ff6 100644 --- a/substrate/frame/nis/src/mock.rs +++ b/substrate/frame/nis/src/mock.rs @@ -56,6 +56,7 @@ impl frame_system::Config for Test { type BlockLength = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = u64; type Hash = H256; type Hashing = BlakeTwo256; @@ -90,6 +91,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = RuntimeHoldReason; type MaxHolds = ConstU32<1>; + type RuntimeTask = RuntimeTask; } impl pallet_balances::Config for Test { @@ -110,6 +112,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } parameter_types! { diff --git a/substrate/frame/node-authorization/src/mock.rs b/substrate/frame/node-authorization/src/mock.rs index 84e3336b3bd6..f98ae4f1ecb6 100644 --- a/substrate/frame/node-authorization/src/mock.rs +++ b/substrate/frame/node-authorization/src/mock.rs @@ -67,6 +67,7 @@ impl frame_system::Config for Test { type SS58Prefix = (); type OnSetCode = (); type MaxConsumers = ConstU32<16>; + type RuntimeTask = RuntimeTask; } ord_parameter_types! { diff --git a/substrate/frame/nomination-pools/src/mock.rs b/substrate/frame/nomination-pools/src/mock.rs index 28c24c428035..cacc97baa589 100644 --- a/substrate/frame/nomination-pools/src/mock.rs +++ b/substrate/frame/nomination-pools/src/mock.rs @@ -187,6 +187,7 @@ impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = sp_core::H256; type Hashing = sp_runtime::traits::BlakeTwo256; type AccountId = AccountId; @@ -217,6 +218,7 @@ impl pallet_balances::Config for Runtime { type ReserveIdentifier = [u8; 8]; type Balance = Balance; type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; diff --git a/substrate/frame/nomination-pools/test-staking/src/mock.rs b/substrate/frame/nomination-pools/test-staking/src/mock.rs index 02c253e62c01..2f7446e5e44f 100644 --- a/substrate/frame/nomination-pools/test-staking/src/mock.rs +++ b/substrate/frame/nomination-pools/test-staking/src/mock.rs @@ -46,6 +46,7 @@ impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type Nonce = Nonce; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = sp_core::H256; type Hashing = sp_runtime::traits::BlakeTwo256; type AccountId = AccountId; @@ -89,6 +90,7 @@ impl pallet_balances::Config for Runtime { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } pallet_staking_reward_curve::build! { diff --git a/substrate/frame/offences/src/mock.rs b/substrate/frame/offences/src/mock.rs index 990ceae5ac01..0c6ba68fdd4e 100644 --- a/substrate/frame/offences/src/mock.rs +++ b/substrate/frame/offences/src/mock.rs @@ -82,6 +82,7 @@ impl frame_system::Config for Runtime { type DbWeight = RocksDbWeight; type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; + type RuntimeTask = RuntimeTask; type RuntimeCall = RuntimeCall; type Hash = H256; type Hashing = BlakeTwo256; diff --git a/substrate/frame/paged-list/src/mock.rs b/substrate/frame/paged-list/src/mock.rs index 390b4a8530dc..d92067601856 100644 --- a/substrate/frame/paged-list/src/mock.rs +++ b/substrate/frame/paged-list/src/mock.rs @@ -45,6 +45,7 @@ impl frame_system::Config for Test { type DbWeight = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = u64; type Hash = H256; type Hashing = BlakeTwo256; diff --git a/substrate/frame/preimage/src/mock.rs b/substrate/frame/preimage/src/mock.rs index 2fb9f36dec45..d782975ef027 100644 --- a/substrate/frame/preimage/src/mock.rs +++ b/substrate/frame/preimage/src/mock.rs @@ -49,6 +49,7 @@ impl frame_system::Config for Test { type BlockLength = (); type DbWeight = RocksDbWeight; type RuntimeOrigin = RuntimeOrigin; + type RuntimeTask = RuntimeTask; type RuntimeCall = RuntimeCall; type Nonce = u64; type Hash = H256; @@ -83,6 +84,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } ord_parameter_types! { diff --git a/substrate/frame/proxy/src/tests.rs b/substrate/frame/proxy/src/tests.rs index 0667be6e1e52..3080a92537ad 100644 --- a/substrate/frame/proxy/src/tests.rs +++ b/substrate/frame/proxy/src/tests.rs @@ -48,6 +48,7 @@ impl frame_system::Config for Test { type BlockHashCount = ConstU64<250>; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type RuntimeEvent = RuntimeEvent; type PalletInfo = PalletInfo; type OnSetCode = (); @@ -64,6 +65,7 @@ impl pallet_balances::Config for Test { type DustRemoval = (); type AccountStore = System; type ExistentialDeposit = ConstU64<1>; + type RuntimeTask = RuntimeTask; } impl pallet_utility::Config for Test { diff --git a/substrate/frame/ranked-collective/src/tests.rs b/substrate/frame/ranked-collective/src/tests.rs index ba8c5a0f937b..b491dc6756d7 100644 --- a/substrate/frame/ranked-collective/src/tests.rs +++ b/substrate/frame/ranked-collective/src/tests.rs @@ -69,6 +69,7 @@ impl frame_system::Config for Test { type SS58Prefix = (); type OnSetCode = (); type MaxConsumers = ConstU32<16>; + type RuntimeTask = RuntimeTask; } #[derive(Clone, PartialEq, Eq, Debug)] diff --git a/substrate/frame/recovery/src/mock.rs b/substrate/frame/recovery/src/mock.rs index 2f2bd866a719..e87ceba66430 100644 --- a/substrate/frame/recovery/src/mock.rs +++ b/substrate/frame/recovery/src/mock.rs @@ -47,6 +47,7 @@ impl frame_system::Config for Test { type BlockLength = (); type DbWeight = (); type RuntimeOrigin = RuntimeOrigin; + type RuntimeTask = RuntimeTask; type RuntimeCall = RuntimeCall; type Nonce = u64; type Hash = H256; @@ -85,6 +86,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } parameter_types! { diff --git a/substrate/frame/referenda/src/mock.rs b/substrate/frame/referenda/src/mock.rs index e44167ed561c..8521bd830001 100644 --- a/substrate/frame/referenda/src/mock.rs +++ b/substrate/frame/referenda/src/mock.rs @@ -67,6 +67,7 @@ impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = u64; @@ -110,6 +111,7 @@ impl pallet_balances::Config for Test { type MaxLocks = ConstU32<10>; type Balance = u64; type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type DustRemoval = (); type ExistentialDeposit = ConstU64<1>; type AccountStore = System; diff --git a/substrate/frame/remark/src/mock.rs b/substrate/frame/remark/src/mock.rs index e597a1ca4dfe..367cc0d16936 100644 --- a/substrate/frame/remark/src/mock.rs +++ b/substrate/frame/remark/src/mock.rs @@ -41,6 +41,7 @@ impl frame_system::Config for Test { type BlockWeights = (); type BlockLength = (); type RuntimeOrigin = RuntimeOrigin; + type RuntimeTask = RuntimeTask; type RuntimeCall = RuntimeCall; type Nonce = u64; type Hash = H256; diff --git a/substrate/frame/root-offences/src/mock.rs b/substrate/frame/root-offences/src/mock.rs index 2d2a5476149f..4f39822e5541 100644 --- a/substrate/frame/root-offences/src/mock.rs +++ b/substrate/frame/root-offences/src/mock.rs @@ -93,6 +93,7 @@ impl frame_system::Config for Test { type Nonce = u64; type Hash = H256; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; @@ -124,6 +125,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } pallet_staking_reward_curve::build! { diff --git a/substrate/frame/safe-mode/src/mock.rs b/substrate/frame/safe-mode/src/mock.rs index 635ee0cfedc0..461edd356aa3 100644 --- a/substrate/frame/safe-mode/src/mock.rs +++ b/substrate/frame/safe-mode/src/mock.rs @@ -39,6 +39,7 @@ impl frame_system::Config for Test { type BlockLength = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = u64; type Hash = H256; type Hashing = BlakeTwo256; @@ -72,6 +73,7 @@ impl pallet_balances::Config for Test { type Balance = u64; type DustRemoval = (); type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type ExistentialDeposit = ConstU64<2>; type AccountStore = System; type WeightInfo = (); diff --git a/substrate/frame/salary/src/tests.rs b/substrate/frame/salary/src/tests.rs index 1136ea746f60..928aeb2890ff 100644 --- a/substrate/frame/salary/src/tests.rs +++ b/substrate/frame/salary/src/tests.rs @@ -73,6 +73,7 @@ impl frame_system::Config for Test { type SS58Prefix = (); type OnSetCode = (); type MaxConsumers = ConstU32<16>; + type RuntimeTask = RuntimeTask; } thread_local! { diff --git a/substrate/frame/scheduler/src/mock.rs b/substrate/frame/scheduler/src/mock.rs index 28e334958d92..68a5c1d18640 100644 --- a/substrate/frame/scheduler/src/mock.rs +++ b/substrate/frame/scheduler/src/mock.rs @@ -125,6 +125,7 @@ impl system::Config for Test { type DbWeight = RocksDbWeight; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = u64; type Hash = H256; type Hashing = BlakeTwo256; diff --git a/substrate/frame/scored-pool/src/mock.rs b/substrate/frame/scored-pool/src/mock.rs index 591c910488b1..f4b7b55822fd 100644 --- a/substrate/frame/scored-pool/src/mock.rs +++ b/substrate/frame/scored-pool/src/mock.rs @@ -59,6 +59,7 @@ impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type Hash = H256; + type RuntimeTask = RuntimeTask; type RuntimeCall = RuntimeCall; type Hashing = BlakeTwo256; type AccountId = u64; @@ -91,6 +92,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } parameter_types! { diff --git a/substrate/frame/session/src/mock.rs b/substrate/frame/session/src/mock.rs index 2db54e1a5975..2dce98710a71 100644 --- a/substrate/frame/session/src/mock.rs +++ b/substrate/frame/session/src/mock.rs @@ -240,6 +240,7 @@ impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = u64; diff --git a/substrate/frame/society/src/mock.rs b/substrate/frame/society/src/mock.rs index a318c2e794b7..455e064171c0 100644 --- a/substrate/frame/society/src/mock.rs +++ b/substrate/frame/society/src/mock.rs @@ -67,6 +67,7 @@ impl frame_system::Config for Test { type Nonce = u64; type Hash = H256; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hashing = BlakeTwo256; type AccountId = u128; type Lookup = IdentityLookup; @@ -90,6 +91,7 @@ impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type Balance = u64; type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type DustRemoval = (); type ExistentialDeposit = ConstU64<1>; type AccountStore = System; diff --git a/substrate/frame/staking/src/mock.rs b/substrate/frame/staking/src/mock.rs index cf08f8be1f27..6f617e20f7bf 100644 --- a/substrate/frame/staking/src/mock.rs +++ b/substrate/frame/staking/src/mock.rs @@ -129,6 +129,7 @@ impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type Nonce = Nonce; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = ::sp_runtime::traits::BlakeTwo256; type AccountId = AccountId; @@ -152,6 +153,7 @@ impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type Balance = Balance; type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; diff --git a/substrate/frame/state-trie-migration/src/lib.rs b/substrate/frame/state-trie-migration/src/lib.rs index 3e69b219bb52..b69c88d1a5e1 100644 --- a/substrate/frame/state-trie-migration/src/lib.rs +++ b/substrate/frame/state-trie-migration/src/lib.rs @@ -1086,6 +1086,7 @@ mod mock { type BlockWeights = (); type BlockLength = (); type RuntimeOrigin = RuntimeOrigin; + type RuntimeTask = RuntimeTask; type RuntimeCall = RuntimeCall; type Nonce = u64; type Hash = H256; @@ -1127,6 +1128,7 @@ mod mock { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } /// Test only Weights for state migration. diff --git a/substrate/frame/statement/src/mock.rs b/substrate/frame/statement/src/mock.rs index 79d2aa7d891d..ceae41a3019f 100644 --- a/substrate/frame/statement/src/mock.rs +++ b/substrate/frame/statement/src/mock.rs @@ -53,6 +53,7 @@ impl frame_system::Config for Test { type BlockLength = (); type DbWeight = RocksDbWeight; type RuntimeOrigin = RuntimeOrigin; + type RuntimeTask = RuntimeTask; type RuntimeCall = RuntimeCall; type Nonce = u64; type Hash = H256; @@ -87,6 +88,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = RuntimeHoldReason; type MaxHolds = (); + type RuntimeTask = RuntimeTask; } ord_parameter_types! { diff --git a/substrate/frame/sudo/src/mock.rs b/substrate/frame/sudo/src/mock.rs index 9e78e474f4e5..dba9676fe0b5 100644 --- a/substrate/frame/sudo/src/mock.rs +++ b/substrate/frame/sudo/src/mock.rs @@ -132,6 +132,7 @@ impl frame_system::Config for Test { type SS58Prefix = (); type OnSetCode = (); type MaxConsumers = ConstU32<16>; + type RuntimeTask = RuntimeTask; } // Implement the logger module's `Config` on the Test runtime. diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/mod.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/mod.rs index 830338f9265f..9dab9f664094 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/mod.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/mod.rs @@ -25,6 +25,7 @@ mod metadata; mod origin; mod outer_enums; mod slash_reason; +mod task; mod unsigned; pub use call::expand_outer_dispatch; @@ -37,4 +38,5 @@ pub use metadata::expand_runtime_metadata; pub use origin::expand_outer_origin; pub use outer_enums::{expand_outer_enum, OuterEnumType}; pub use slash_reason::expand_outer_slash_reason; +pub use task::expand_outer_task; pub use unsigned::expand_outer_validate_unsigned; diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs new file mode 100644 index 000000000000..34d62a7c3594 --- /dev/null +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs @@ -0,0 +1,105 @@ +// 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 + +use crate::construct_runtime::{parse::PalletPath, Pallet}; +use proc_macro2::{Ident, TokenStream}; +use quote::quote; + +/// Expands aggregate `RuntimeTask` enum. +pub fn expand_outer_task(pallet_decls: &[Pallet], scrate: &TokenStream) -> TokenStream { + let mut conversion_fns = Vec::new(); + let mut task_variants = Vec::new(); + for decl in pallet_decls { + if let Some(_) = decl.find_part("Task") { + // TODO: for some reason `find_part` above never finds `Task` even when it is + // clearly in the pallet + let variant_name = &decl.name; + let path = &decl.path; + let index = decl.index; + + conversion_fns.push(expand_conversion_fn(path, variant_name)); + + task_variants.push(expand_variant(index, path, variant_name)); + } + } + use quote::ToTokens; + if !task_variants.is_empty() { + println!( + "{:#?}", + task_variants + .iter() + .map(|item| item.to_token_stream().to_string()) + .collect::>() + ); + } + + quote! { + /// An aggregation of all `Task` enums across all pallets included in the current runtime. + #[derive( + Clone, Eq, PartialEq, + #scrate::__private::codec::Encode, #scrate::__private::codec::Decode, + // #scrate::__private::codec::MaxEncodedLen, + #scrate::__private::scale_info::TypeInfo, + #scrate::__private::RuntimeDebug, + )] + pub enum RuntimeTask { + #( #task_variants )* + } + + impl #scrate::traits::AggregatedTask for RuntimeTask { + fn is_valid(&self) -> bool { + use #scrate::traits::tasks::prelude::*; + todo!(); + } + + fn run(&self) -> Result<(), #scrate::traits::tasks::prelude::DispatchError> { + todo!(); + } + + fn weight(&self) -> #scrate::pallet_prelude::Weight { + todo!(); + } + + fn task_index(&self) -> u64 { + todo!(); + } + } + + #( #conversion_fns )* + } +} + +fn expand_conversion_fn(path: &PalletPath, variant_name: &Ident) -> TokenStream { + // Todo: Replace `Runtime` with the actual runtime ident + // `pallet` will probably not be needed when `Task` is generated by macro + quote! { + impl From<#path::pallet::Task> for RuntimeTask { + fn from(hr: #path::pallet::Task) -> Self { + RuntimeTask::#variant_name(hr) + } + } + } +} + +fn expand_variant(index: u8, path: &PalletPath, variant_name: &Ident) -> TokenStream { + // Todo: Replace `Runtime` with the actual runtime ident + // `pallet` will probably not be needed when `Task` is generated by macro + quote! { + #[codec(index = #index)] + #variant_name(#path::pallet::Task), + } +} diff --git a/substrate/frame/support/procedural/src/construct_runtime/mod.rs b/substrate/frame/support/procedural/src/construct_runtime/mod.rs index f42dd837e3a9..605571381942 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/mod.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/mod.rs @@ -385,6 +385,7 @@ fn construct_runtime_final_expansion( let pallet_to_index = decl_pallet_runtime_setup(&name, &pallets, &scrate); let dispatch = expand::expand_outer_dispatch(&name, system_pallet, &pallets, &scrate); + let tasks = expand::expand_outer_task(&pallets, &scrate); let metadata = expand::expand_runtime_metadata( &name, &pallets, @@ -472,6 +473,8 @@ fn construct_runtime_final_expansion( #dispatch + #tasks + #metadata #outer_config diff --git a/substrate/frame/support/procedural/src/construct_runtime/parse.rs b/substrate/frame/support/procedural/src/construct_runtime/parse.rs index 9b08e1646975..88f3f14dc86c 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/parse.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/parse.rs @@ -42,6 +42,7 @@ mod keyword { syn::custom_keyword!(ValidateUnsigned); syn::custom_keyword!(FreezeReason); syn::custom_keyword!(HoldReason); + syn::custom_keyword!(Task); syn::custom_keyword!(LockId); syn::custom_keyword!(SlashReason); syn::custom_keyword!(exclude_parts); @@ -404,6 +405,7 @@ pub enum PalletPartKeyword { ValidateUnsigned(keyword::ValidateUnsigned), FreezeReason(keyword::FreezeReason), HoldReason(keyword::HoldReason), + Task(keyword::Task), LockId(keyword::LockId), SlashReason(keyword::SlashReason), } @@ -434,6 +436,8 @@ impl Parse for PalletPartKeyword { Ok(Self::FreezeReason(input.parse()?)) } else if lookahead.peek(keyword::HoldReason) { Ok(Self::HoldReason(input.parse()?)) + } else if lookahead.peek(keyword::Task) { + Ok(Self::Task(input.parse()?)) } else if lookahead.peek(keyword::LockId) { Ok(Self::LockId(input.parse()?)) } else if lookahead.peek(keyword::SlashReason) { @@ -459,6 +463,7 @@ impl PalletPartKeyword { Self::ValidateUnsigned(_) => "ValidateUnsigned", Self::FreezeReason(_) => "FreezeReason", Self::HoldReason(_) => "HoldReason", + Self::Task(_) => "Task", Self::LockId(_) => "LockId", Self::SlashReason(_) => "SlashReason", } @@ -471,7 +476,7 @@ impl PalletPartKeyword { /// Returns the names of all pallet parts that allow to have a generic argument. fn all_generic_arg() -> &'static [&'static str] { - &["Event", "Error", "Origin", "Config"] + &["Event", "Error", "Origin", "Config", "Task"] } } @@ -489,6 +494,7 @@ impl ToTokens for PalletPartKeyword { Self::ValidateUnsigned(inner) => inner.to_tokens(tokens), Self::FreezeReason(inner) => inner.to_tokens(tokens), Self::HoldReason(inner) => inner.to_tokens(tokens), + Self::Task(inner) => inner.to_tokens(tokens), Self::LockId(inner) => inner.to_tokens(tokens), Self::SlashReason(inner) => inner.to_tokens(tokens), } diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index 9957cf1cff85..8d26f4ed1837 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -646,7 +646,6 @@ pub fn storage_alias(attributes: TokenStream, input: TokenStream) -> TokenStream /// ``` /// /// where `TestDefaultConfig` was defined and registered as follows: -/// /// ```ignore /// pub struct TestDefaultConfig; /// @@ -673,7 +672,6 @@ pub fn storage_alias(attributes: TokenStream, input: TokenStream) -> TokenStream /// ``` /// /// The above call to `derive_impl` would expand to roughly the following: -/// /// ```ignore /// impl frame_system::Config for Test { /// use frame_system::config_preludes::TestDefaultConfig; @@ -876,12 +874,14 @@ pub fn inject_runtime_type(_: TokenStream, tokens: TokenStream) -> TokenStream { let item = syn::parse_macro_input!(item as TraitItemType); if item.ident != "RuntimeCall" && item.ident != "RuntimeEvent" && + item.ident != "RuntimeTask" && item.ident != "RuntimeOrigin" && item.ident != "PalletInfo" { return syn::Error::new_spanned( item, - "`#[inject_runtime_type]` can only be attached to `RuntimeCall`, `RuntimeEvent`, `RuntimeOrigin` or `PalletInfo`", + "`#[inject_runtime_type]` can only be attached to `RuntimeCall`, `RuntimeEvent`, \ + `RuntimeTask`, `RuntimeOrigin` or `PalletInfo`", ) .to_compile_error() .into(); diff --git a/substrate/frame/support/procedural/src/pallet/expand/tt_default_parts.rs b/substrate/frame/support/procedural/src/pallet/expand/tt_default_parts.rs index 86db56c776df..f322fe17a7c4 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/tt_default_parts.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/tt_default_parts.rs @@ -31,6 +31,19 @@ pub fn expand_tt_default_parts(def: &mut Def) -> proc_macro2::TokenStream { let call_part = def.call.as_ref().map(|_| quote::quote!(Call,)); + // TODO: maybe allow `task_enum: Option` to sit on `Def` itself? + let task_part = def.item.content.as_ref().and_then(|(_, items)| { + items.iter().find_map(|item| { + if let syn::Item::Enum(item_enum) = item { + if item_enum.ident == "Task" { + println!("found task enum in tt_default_parts!"); + return Some(item_enum) + } + } + None + }) + }); + let storage_part = (!def.storages.is_empty()).then(|| quote::quote!(Storage,)); let event_part = def.event.as_ref().map(|event| { @@ -101,7 +114,7 @@ pub fn expand_tt_default_parts(def: &mut Def) -> proc_macro2::TokenStream { tokens = [{ expanded::{ Pallet, #call_part #storage_part #event_part #error_part #origin_part #config_part - #inherent_part #validate_unsigned_part #freeze_reason_part + #inherent_part #validate_unsigned_part #freeze_reason_part #task_part #hold_reason_part #lock_id_part #slash_reason_part } }] diff --git a/substrate/frame/support/procedural/src/pallet/parse/composite.rs b/substrate/frame/support/procedural/src/pallet/parse/composite.rs index cb554a116175..6c21e469ca67 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/composite.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/composite.rs @@ -25,11 +25,14 @@ pub mod keyword { syn::custom_keyword!(HoldReason); syn::custom_keyword!(LockId); syn::custom_keyword!(SlashReason); + syn::custom_keyword!(Task); + pub enum CompositeKeyword { FreezeReason(FreezeReason), HoldReason(HoldReason), LockId(LockId), SlashReason(SlashReason), + Task(Task), } impl ToTokens for CompositeKeyword { @@ -40,6 +43,7 @@ pub mod keyword { HoldReason(inner) => inner.to_tokens(tokens), LockId(inner) => inner.to_tokens(tokens), SlashReason(inner) => inner.to_tokens(tokens), + Task(inner) => inner.to_tokens(tokens), } } } @@ -55,6 +59,8 @@ pub mod keyword { Ok(Self::LockId(input.parse()?)) } else if lookahead.peek(SlashReason) { Ok(Self::SlashReason(input.parse()?)) + } else if lookahead.peek(Task) { + Ok(Self::Task(input.parse()?)) } else { Err(lookahead.error()) } @@ -70,6 +76,7 @@ pub mod keyword { match self { FreezeReason(_) => "FreezeReason", HoldReason(_) => "HoldReason", + Task(_) => "Task", LockId(_) => "LockId", SlashReason(_) => "SlashReason", } @@ -79,7 +86,7 @@ pub mod keyword { } pub struct CompositeDef { - /// The index of the HoldReason item in the pallet module. + /// The index of the CompositeDef item in the pallet module. pub index: usize, /// The composite keyword used (contains span). pub composite_keyword: keyword::CompositeKeyword, diff --git a/substrate/frame/support/procedural/src/pallet/parse/mod.rs b/substrate/frame/support/procedural/src/pallet/parse/mod.rs index 0f5e5f113661..44bf12dc19f7 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/mod.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/mod.rs @@ -33,6 +33,7 @@ pub mod inherent; pub mod origin; pub mod pallet_struct; pub mod storage; +pub mod tasks; pub mod type_value; pub mod validate_unsigned; @@ -49,6 +50,8 @@ pub struct Def { pub pallet_struct: pallet_struct::PalletStructDef, pub hooks: Option, pub call: Option, + pub tasks: Option, + pub task_enum: Option, pub storages: Vec, pub error: Option, pub event: Option, @@ -84,6 +87,8 @@ impl Def { let mut pallet_struct = None; let mut hooks = None; let mut call = None; + let mut tasks = None; + let mut task_enum = None; let mut error = None; let mut event = None; let mut origin = None; @@ -97,6 +102,14 @@ impl Def { let mut composites: Vec = vec![]; for (index, item) in items.iter_mut().enumerate() { + // find manually specified `Task` enum, if present + if let syn::Item::Enum(item_enum) = item { + if item_enum.ident == "Task" { + println!("found task enum while parsing Def!"); + task_enum = Some(item_enum.clone()); + } + } + let pallet_attr: Option = helper::take_first_item_pallet_attr(item)?; match pallet_attr { @@ -118,6 +131,8 @@ impl Def { }, Some(PalletAttr::RuntimeCall(cw, span)) if call.is_none() => call = Some(call::CallDef::try_from(span, index, item, dev_mode, cw)?), + Some(PalletAttr::Tasks(span)) if tasks.is_none() => + tasks = Some(tasks::TasksDef::try_from(span, index, item)?), Some(PalletAttr::Error(span)) if error.is_none() => error = Some(error::ErrorDef::try_from(span, index, item)?), Some(PalletAttr::RuntimeEvent(span)) if event.is_none() => @@ -198,6 +213,8 @@ impl Def { .ok_or_else(|| syn::Error::new(item_span, "Missing `#[pallet::pallet]`"))?, hooks, call, + tasks, + task_enum, extra_constants, genesis_config, genesis_build, @@ -408,6 +425,7 @@ impl GenericKind { mod keyword { syn::custom_keyword!(origin); syn::custom_keyword!(call); + syn::custom_keyword!(tasks); syn::custom_keyword!(weight); syn::custom_keyword!(event); syn::custom_keyword!(config); @@ -471,6 +489,7 @@ enum PalletAttr { /// to zero. Now when there is a `weight` attribute on the `#[pallet::call]`, then that is used /// instead of the zero weight. So to say: it works together with `dev_mode`. RuntimeCall(Option, proc_macro2::Span), + Tasks(proc_macro2::Span), Error(proc_macro2::Span), RuntimeEvent(proc_macro2::Span), RuntimeOrigin(proc_macro2::Span), @@ -491,6 +510,7 @@ impl PalletAttr { Self::Pallet(span) => *span, Self::Hooks(span) => *span, Self::RuntimeCall(_, span) => *span, + Self::Tasks(span) => *span, Self::Error(span) => *span, Self::RuntimeEvent(span) => *span, Self::RuntimeOrigin(span) => *span, @@ -535,6 +555,8 @@ impl syn::parse::Parse for PalletAttr { false => Some(InheritedCallWeightAttr::parse(&content)?), }; Ok(PalletAttr::RuntimeCall(attr, span)) + } else if lookahead.peek(keyword::tasks) { + Ok(PalletAttr::Tasks(content.parse::()?.span())) } else if lookahead.peek(keyword::error) { Ok(PalletAttr::Error(content.parse::()?.span())) } else if lookahead.peek(keyword::event) { diff --git a/substrate/frame/support/procedural/src/pallet/parse/tasks.rs b/substrate/frame/support/procedural/src/pallet/parse/tasks.rs new file mode 100644 index 000000000000..23715014585a --- /dev/null +++ b/substrate/frame/support/procedural/src/pallet/parse/tasks.rs @@ -0,0 +1,121 @@ +// 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. + +use derive_syn_parse::Parse; +use proc_macro2::Span; +use syn::{ + token::{Bracket, Paren}, + Expr, Ident, Item, LitInt, Result, Token, +}; + +pub mod keywords { + use syn::custom_keyword; + + custom_keyword!(tasks); + custom_keyword!(task_list); + custom_keyword!(condition); + custom_keyword!(task_index); + custom_keyword!(pallet); +} + +pub struct TasksDef; + +impl TasksDef { + pub fn try_from(_span: Span, _index: usize, _item: &mut Item) -> Result { + // TODO: fill in + Ok(TasksDef {}) + } +} + +#[derive(Parse)] +pub enum TaskAttrType { + #[peek(keywords::task_list, name = "#[pallet::task_list(..)]")] + TaskList { + _tasks: keywords::task_list, + #[paren] + _paren: Paren, + #[inside(_paren)] + expr: Expr, + }, + #[peek(keywords::task_index, name = "#[pallet::task_index(..)")] + TaskIndex { + _task_index: keywords::task_index, + #[paren] + _paren: Paren, + #[inside(_paren)] + index: LitInt, + }, + #[peek(keywords::condition, name = "#[pallet::condition(..)")] + Condition { + _condition: keywords::condition, + #[paren] + _paren: Paren, + #[inside(_paren)] + _pipe1: Token![|], + #[inside(_paren)] + _ident: Ident, + #[inside(_paren)] + _pipe2: Token![|], + #[inside(_paren)] + expr: Expr, + }, + // TODO: Tasks +} + +#[derive(Parse)] +pub struct PalletTaskAttr { + _pound: Token![#], + #[bracket] + _bracket: Bracket, + #[inside(_bracket)] + _pallet: keywords::pallet, + #[inside(_bracket)] + _colons: Token![::], + #[inside(_bracket)] + _attr: TaskAttrType, +} + +#[cfg(test)] +use syn::parse2; + +#[cfg(test)] +use quote::quote; + +#[test] +fn test_parse_pallet_task_list_() { + parse2::(quote!(#[pallet::task_list(Something::iter())])).unwrap(); + assert!(parse2::(quote!(#[pallet::task_list()])).is_err()); + assert!(parse2::(quote!(#[pallet::tasks_list(iter())])).is_err()); + assert!(parse2::(quote!(#[pallet::task_list])).is_err()); +} + +#[test] +fn test_parse_pallet_task_index() { + parse2::(quote!(#[pallet::task_index(3)])).unwrap(); + parse2::(quote!(#[pallet::task_index(0)])).unwrap(); + parse2::(quote!(#[pallet::task_index(17)])).unwrap(); + assert!(parse2::(quote!(#[pallet::task_index])).is_err()); + assert!(parse2::(quote!(#[pallet::task_index("hey")])).is_err()); +} + +#[test] +fn test_parse_pallet_condition() { + parse2::(quote!(#[pallet::condition(|x| x.is_some())])).unwrap(); + parse2::(quote!(#[pallet::condition(|_x| some_expr())])).unwrap(); + assert!(parse2::(quote!(#[pallet::condition(x.is_some())])).is_err()); + assert!(parse2::(quote!(#[pallet::condition(|| something())])).is_err()); +} diff --git a/substrate/frame/support/src/dispatch.rs b/substrate/frame/support/src/dispatch.rs index eb1fc524200b..b39c7856f41f 100644 --- a/substrate/frame/support/src/dispatch.rs +++ b/substrate/frame/support/src/dispatch.rs @@ -671,6 +671,7 @@ mod weight_tests { type BaseCallFilter: crate::traits::Contains; type RuntimeOrigin; type RuntimeCall; + type RuntimeTask; type PalletInfo: crate::traits::PalletInfo; type DbWeight: Get; } @@ -767,6 +768,7 @@ mod weight_tests { type BaseCallFilter = crate::traits::Everything; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type DbWeight = DbWeight; type PalletInfo = PalletInfo; } diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index a7106780e021..35ad47583e92 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -819,8 +819,9 @@ pub mod pallet_prelude { StorageList, }, traits::{ - BuildGenesisConfig, ConstU32, EnsureOrigin, Get, GetDefault, GetStorageVersion, Hooks, - IsType, PalletInfoAccess, StorageInfoTrait, StorageVersion, TypedGet, + AggregatedTask, BuildGenesisConfig, ConstU32, EnsureOrigin, Get, GetDefault, + GetStorageVersion, Hooks, IsType, PalletInfoAccess, StorageInfoTrait, StorageVersion, + Task, TypedGet, }, Blake2_128, Blake2_128Concat, Blake2_256, CloneNoBound, DebugNoBound, EqNoBound, Identity, PartialEqNoBound, RuntimeDebugNoBound, Twox128, Twox256, Twox64Concat, diff --git a/substrate/frame/support/src/storage/generator/mod.rs b/substrate/frame/support/src/storage/generator/mod.rs index bac9f642e37d..71a32135030c 100644 --- a/substrate/frame/support/src/storage/generator/mod.rs +++ b/substrate/frame/support/src/storage/generator/mod.rs @@ -63,6 +63,7 @@ mod tests { type BaseCallFilter: crate::traits::Contains; type RuntimeOrigin; type RuntimeCall; + type RuntimeTask; type PalletInfo: crate::traits::PalletInfo; type DbWeight: Get; } @@ -129,6 +130,7 @@ mod tests { type BaseCallFilter = crate::traits::Everything; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type PalletInfo = PalletInfo; type DbWeight = (); } diff --git a/substrate/frame/support/src/tests/mod.rs b/substrate/frame/support/src/tests/mod.rs index db458880db68..96ac05d38764 100644 --- a/substrate/frame/support/src/tests/mod.rs +++ b/substrate/frame/support/src/tests/mod.rs @@ -49,6 +49,8 @@ pub mod frame_system { type RuntimeCall = (); #[inject_runtime_type] type PalletInfo = (); + #[inject_runtime_type] + type RuntimeTask = (); type DbWeight = (); } } @@ -69,6 +71,8 @@ pub mod frame_system { #[pallet::no_default_bounds] type RuntimeCall; #[pallet::no_default_bounds] + type RuntimeTask; + #[pallet::no_default_bounds] type PalletInfo: crate::traits::PalletInfo; type DbWeight: Get; } @@ -196,6 +200,7 @@ crate::construct_runtime!( impl Config for Runtime { type Block = Block; type AccountId = AccountId; + type RuntimeTask = RuntimeTask; } fn new_test_ext() -> TestExternalities { diff --git a/substrate/frame/support/src/traits.rs b/substrate/frame/support/src/traits.rs index f669046f858f..fbc70e584b34 100644 --- a/substrate/frame/support/src/traits.rs +++ b/substrate/frame/support/src/traits.rs @@ -122,6 +122,9 @@ pub use safe_mode::{SafeMode, SafeModeError, SafeModeNotify}; mod tx_pause; pub use tx_pause::{TransactionPause, TransactionPauseError}; +pub mod tasks; +pub use tasks::{AggregatedTask, Task}; + #[cfg(feature = "try-runtime")] mod try_runtime; #[cfg(feature = "try-runtime")] diff --git a/substrate/frame/support/src/traits/tasks.rs b/substrate/frame/support/src/traits/tasks.rs new file mode 100644 index 000000000000..c52fc7d17917 --- /dev/null +++ b/substrate/frame/support/src/traits/tasks.rs @@ -0,0 +1,74 @@ +// 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. + +//! Contains the [`Task`] trait, which defines a general-purpose way for defining and executing +//! service work, and supporting types. + +/// Contain's re-exports of all the supporting types for the [`Task`] trait. Used in the macro +/// expansion of `RuntimeTask`. +pub mod prelude { + pub use codec::FullCodec; + pub use scale_info::TypeInfo; + pub use sp_runtime::DispatchError; + pub use sp_std::{fmt::Debug, iter::Iterator}; + pub use sp_weights::Weight; +} + +use prelude::*; + +/// A general-purpose trait which defines a type of service work (i.e., work to performed by an +/// off-chain worker) including methods for enumerating, validating, indexing, and running +/// tasks of this type. +pub trait Task: Sized + FullCodec + TypeInfo + Clone + Debug + PartialEq + Eq { + type Enumeration: Iterator; + + /// A unique value representing this `Task`. Analogous to `call_index`, but for tasks. + const TASK_INDEX: u64; + + /// Inspects the pallet's state and enumerates tasks of this type. + fn enumerate() -> Self::Enumeration; + + /// Checks if a particular instance of this `Task` variant is a valid piece of work. + fn is_valid(&self) -> bool; + + /// Performs the work for this particular `Task` variant. + fn run(&self) -> Result<(), DispatchError>; + + /// Returns the weight of executing this `Task`. + fn weight(&self) -> Weight; + + /// A unique value representing this `Task`. Analogous to `call_index`, but for tasks. + fn task_index(&self) -> u64 { + Self::TASK_INDEX + } +} + +/// Contains a subset of [`Task`] that can be generalized over the aggregated `RuntimeTask` +/// enum. +pub trait AggregatedTask: Sized + FullCodec + TypeInfo + Clone + Debug + PartialEq + Eq { + /// Checks if a particular instance of this `Task` variant is a valid piece of work. + fn is_valid(&self) -> bool; + + /// Performs the work for this particular `Task` variant. + fn run(&self) -> Result<(), DispatchError>; + + /// Returns the weight of executing this `Task`. + fn weight(&self) -> Weight; + + /// A unique value representing this `Task`. Analogous to `call_index`, but for tasks. + fn task_index(&self) -> u64; +} diff --git a/substrate/frame/support/test/compile_pass/src/lib.rs b/substrate/frame/support/test/compile_pass/src/lib.rs index bf90d73acb32..24d8b88e94af 100644 --- a/substrate/frame/support/test/compile_pass/src/lib.rs +++ b/substrate/frame/support/test/compile_pass/src/lib.rs @@ -67,6 +67,7 @@ impl frame_system::Config for Runtime { type RuntimeEvent = RuntimeEvent; type PalletInfo = PalletInfo; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type DbWeight = (); type OnNewAccount = (); type OnKilledAccount = (); diff --git a/substrate/frame/support/test/src/lib.rs b/substrate/frame/support/test/src/lib.rs index 6b38d42d33d0..a8a723375033 100644 --- a/substrate/frame/support/test/src/lib.rs +++ b/substrate/frame/support/test/src/lib.rs @@ -50,6 +50,8 @@ pub mod pallet { + From>; /// The runtime call type. type RuntimeCall; + /// Contains an aggregation of all tasks in this runtime. + type RuntimeTask; /// The runtime event type. type RuntimeEvent: Parameter + Member diff --git a/substrate/frame/support/test/tests/construct_runtime.rs b/substrate/frame/support/test/tests/construct_runtime.rs index 9ad51ad530eb..dbb20851aacd 100644 --- a/substrate/frame/support/test/tests/construct_runtime.rs +++ b/substrate/frame/support/test/tests/construct_runtime.rs @@ -282,6 +282,7 @@ impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type RuntimeEvent = RuntimeEvent; type PalletInfo = PalletInfo; type OnSetCode = (); diff --git a/substrate/frame/support/test/tests/final_keys.rs b/substrate/frame/support/test/tests/final_keys.rs index 765afaf1e660..8989e8da69a2 100644 --- a/substrate/frame/support/test/tests/final_keys.rs +++ b/substrate/frame/support/test/tests/final_keys.rs @@ -217,6 +217,7 @@ impl frame_system::Config for Runtime { type BlockHashCount = ConstU32<10>; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type RuntimeEvent = RuntimeEvent; type PalletInfo = PalletInfo; type OnSetCode = (); diff --git a/substrate/frame/support/test/tests/genesisconfig.rs b/substrate/frame/support/test/tests/genesisconfig.rs index c6781220692a..cf10a0f762ba 100644 --- a/substrate/frame/support/test/tests/genesisconfig.rs +++ b/substrate/frame/support/test/tests/genesisconfig.rs @@ -86,6 +86,7 @@ impl frame_system::Config for Test { type BlockHashCount = ConstU32<10>; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type RuntimeEvent = RuntimeEvent; type PalletInfo = PalletInfo; type OnSetCode = (); diff --git a/substrate/frame/support/test/tests/instance.rs b/substrate/frame/support/test/tests/instance.rs index 43a93df9dea4..ea8e52747434 100644 --- a/substrate/frame/support/test/tests/instance.rs +++ b/substrate/frame/support/test/tests/instance.rs @@ -306,6 +306,7 @@ impl frame_system::Config for Runtime { type BlockHashCount = ConstU32<10>; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type RuntimeEvent = RuntimeEvent; type PalletInfo = PalletInfo; type OnSetCode = (); diff --git a/substrate/frame/support/test/tests/issue2219.rs b/substrate/frame/support/test/tests/issue2219.rs index 4016707b51a8..7373d70fe574 100644 --- a/substrate/frame/support/test/tests/issue2219.rs +++ b/substrate/frame/support/test/tests/issue2219.rs @@ -168,6 +168,7 @@ impl frame_system::Config for Runtime { type BlockHashCount = ConstU64<10>; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type RuntimeEvent = RuntimeEvent; type PalletInfo = PalletInfo; type OnSetCode = (); diff --git a/substrate/frame/support/test/tests/origin.rs b/substrate/frame/support/test/tests/origin.rs index 5682bb500c7e..fedeb344a139 100644 --- a/substrate/frame/support/test/tests/origin.rs +++ b/substrate/frame/support/test/tests/origin.rs @@ -177,6 +177,7 @@ impl frame_system::Config for RuntimeOriginTest { type BlockHashCount = ConstU32<10>; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type RuntimeEvent = RuntimeEvent; type PalletInfo = PalletInfo; type OnSetCode = (); diff --git a/substrate/frame/support/test/tests/pallet.rs b/substrate/frame/support/test/tests/pallet.rs index 1898246470c7..da07b57b24bb 100644 --- a/substrate/frame/support/test/tests/pallet.rs +++ b/substrate/frame/support/test/tests/pallet.rs @@ -692,6 +692,7 @@ impl frame_system::Config for Runtime { type Lookup = sp_runtime::traits::IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type BlockHashCount = ConstU32<250>; type BlockWeights = (); type BlockLength = (); diff --git a/substrate/frame/support/test/tests/pallet_instance.rs b/substrate/frame/support/test/tests/pallet_instance.rs index 8d2d52d18852..dee671da35ea 100644 --- a/substrate/frame/support/test/tests/pallet_instance.rs +++ b/substrate/frame/support/test/tests/pallet_instance.rs @@ -296,6 +296,7 @@ impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = sp_runtime::testing::H256; type Hashing = sp_runtime::traits::BlakeTwo256; type AccountId = u64; diff --git a/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs b/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs index a8250f8b1532..c90c5ecf6971 100644 --- a/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs +++ b/substrate/frame/support/test/tests/pallet_outer_enums_explicit.rs @@ -32,6 +32,7 @@ impl frame_system::Config for Runtime { type BlockHashCount = ConstU32<10>; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type RuntimeEvent = RuntimeEvent; type PalletInfo = PalletInfo; type OnSetCode = (); @@ -90,6 +91,8 @@ fn module_error_outer_enum_expand_explicit() { frame_system::Error::NonDefaultComposite => (), frame_system::Error::NonZeroRefCount => (), frame_system::Error::CallFiltered => (), + frame_system::Error::InvalidTask => (), + frame_system::Error::FailedTask => (), frame_system::Error::__Ignore(_, _) => (), }, diff --git a/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs b/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs index 191f095f5d78..ed08bf66287e 100644 --- a/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs +++ b/substrate/frame/support/test/tests/pallet_outer_enums_implicit.rs @@ -32,6 +32,7 @@ impl frame_system::Config for Runtime { type BlockHashCount = ConstU32<10>; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type RuntimeEvent = RuntimeEvent; type PalletInfo = PalletInfo; type OnSetCode = (); @@ -90,6 +91,8 @@ fn module_error_outer_enum_expand_implicit() { frame_system::Error::NonDefaultComposite => (), frame_system::Error::NonZeroRefCount => (), frame_system::Error::CallFiltered => (), + frame_system::Error::InvalidTask => (), + frame_system::Error::FailedTask => (), frame_system::Error::__Ignore(_, _) => (), }, diff --git a/substrate/frame/support/test/tests/runtime_metadata.rs b/substrate/frame/support/test/tests/runtime_metadata.rs index a545735f2b1e..debdce9289ff 100644 --- a/substrate/frame/support/test/tests/runtime_metadata.rs +++ b/substrate/frame/support/test/tests/runtime_metadata.rs @@ -35,6 +35,7 @@ impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = sp_runtime::testing::H256; type Hashing = sp_runtime::traits::BlakeTwo256; type AccountId = u64; diff --git a/substrate/frame/support/test/tests/storage_layers.rs b/substrate/frame/support/test/tests/storage_layers.rs index b825c85f9564..34230af622fa 100644 --- a/substrate/frame/support/test/tests/storage_layers.rs +++ b/substrate/frame/support/test/tests/storage_layers.rs @@ -70,6 +70,7 @@ impl frame_system::Config for Runtime { type BlockLength = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = Nonce; type Hash = sp_runtime::testing::H256; type Hashing = sp_runtime::traits::BlakeTwo256; diff --git a/substrate/frame/support/test/tests/storage_transaction.rs b/substrate/frame/support/test/tests/storage_transaction.rs index c47743308609..7a61a44714b3 100644 --- a/substrate/frame/support/test/tests/storage_transaction.rs +++ b/substrate/frame/support/test/tests/storage_transaction.rs @@ -95,6 +95,7 @@ impl frame_system::Config for Runtime { type BlockHashCount = ConstU32<10>; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type RuntimeEvent = RuntimeEvent; type PalletInfo = PalletInfo; type OnSetCode = (); diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs index 84b6dc031457..0d24f1c7f08e 100644 --- a/substrate/frame/system/src/lib.rs +++ b/substrate/frame/system/src/lib.rs @@ -240,6 +240,8 @@ pub mod pallet { type RuntimeCall = (); #[inject_runtime_type] type PalletInfo = (); + #[inject_runtime_type] + type RuntimeTask = (); type BaseCallFilter = frame_support::traits::Everything; type BlockHashCount = frame_support::traits::ConstU64<10>; type OnSetCode = (); @@ -293,6 +295,10 @@ pub mod pallet { + Debug + From>; + /// The aggregated `RuntimeTask` type. + #[pallet::no_default_bounds] + type RuntimeTask: AggregatedTask; + /// This stores the number of previous transactions associated with a sender account. type Nonce: Parameter + Member @@ -520,6 +526,28 @@ pub mod pallet { Self::deposit_event(Event::Remarked { sender: who, hash }); Ok(().into()) } + + #[pallet::call_index(8)] + #[pallet::weight(task.weight())] + pub fn do_task(origin: OriginFor, task: T::RuntimeTask) -> DispatchResultWithPostInfo { + ensure_signed(origin)?; + + if !task.is_valid() { + return Err(Error::::InvalidTask.into()) + } + + Self::deposit_event(Event::TaskStarted { task: task.clone() }); + if let Err(err) = task.run() { + Self::deposit_event(Event::TaskFailed { task, err }); + return Err(Error::::FailedTask.into()) + } + + // Emit a success event, if your design includes events for this pallet. + Self::deposit_event(Event::TaskCompleted { task }); + + // Return success. + Ok(().into()) + } } /// Event for the System pallet. @@ -537,6 +565,12 @@ pub mod pallet { KilledAccount { account: T::AccountId }, /// On on-chain remark happened. Remarked { sender: T::AccountId, hash: T::Hash }, + /// A [`Task`] has started executing + TaskStarted { task: T::RuntimeTask }, + /// A [`Task`] has finished executing. + TaskCompleted { task: T::RuntimeTask }, + /// A [`Task`] failed during execution. + TaskFailed { task: T::RuntimeTask, err: DispatchError }, } /// Error for the System pallet @@ -558,6 +592,10 @@ pub mod pallet { NonZeroRefCount, /// The origin filter prevent the call to be dispatched. CallFiltered, + /// The specified [`Task`] is not valid. + InvalidTask, + /// The specified [`Task`] failed during execution. + FailedTask, } /// Exposed trait-generic origin type. diff --git a/substrate/frame/system/src/mock.rs b/substrate/frame/system/src/mock.rs index c016ea9e1cd1..670dbb266b03 100644 --- a/substrate/frame/system/src/mock.rs +++ b/substrate/frame/system/src/mock.rs @@ -91,6 +91,7 @@ impl Config for Test { type BlockLength = RuntimeBlockLength; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = u64; type Hash = H256; type Hashing = BlakeTwo256; diff --git a/substrate/frame/timestamp/src/mock.rs b/substrate/frame/timestamp/src/mock.rs index 418d257b3f00..f56b5eaab445 100644 --- a/substrate/frame/timestamp/src/mock.rs +++ b/substrate/frame/timestamp/src/mock.rs @@ -50,6 +50,7 @@ impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = u64; diff --git a/substrate/frame/tips/src/tests.rs b/substrate/frame/tips/src/tests.rs index a700892d4270..1282d42d13d0 100644 --- a/substrate/frame/tips/src/tests.rs +++ b/substrate/frame/tips/src/tests.rs @@ -61,6 +61,7 @@ impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = u128; // u64 is not enough to hold bytes used to generate bounty account @@ -85,6 +86,7 @@ impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type Balance = u64; type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type DustRemoval = (); type ExistentialDeposit = ConstU64<1>; type AccountStore = System; diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs index bfbe8b4178ce..b694a2017c6c 100644 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs @@ -86,6 +86,7 @@ impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = AccountId; @@ -111,6 +112,7 @@ parameter_types! { impl pallet_balances::Config for Runtime { type Balance = Balance; type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type DustRemoval = (); type ExistentialDeposit = ConstU64<10>; type AccountStore = System; diff --git a/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs b/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs index b8d7b523ca25..dd6b4e0dbd0f 100644 --- a/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs @@ -78,6 +78,7 @@ impl frame_system::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = AccountId; @@ -114,6 +115,7 @@ impl pallet_balances::Config for Runtime { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } impl WeightToFeeT for WeightToFee { diff --git a/substrate/frame/transaction-payment/src/mock.rs b/substrate/frame/transaction-payment/src/mock.rs index 97253be46305..0f9b4369d645 100644 --- a/substrate/frame/transaction-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/src/mock.rs @@ -76,6 +76,7 @@ impl frame_system::Config for Runtime { type DbWeight = (); type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; + type RuntimeTask = RuntimeTask; type RuntimeCall = RuntimeCall; type Hash = H256; type Hashing = BlakeTwo256; @@ -109,6 +110,7 @@ impl pallet_balances::Config for Runtime { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } impl WeightToFeeT for WeightToFee { diff --git a/substrate/frame/transaction-storage/src/mock.rs b/substrate/frame/transaction-storage/src/mock.rs index 243e26b55905..f72eb905ddc9 100644 --- a/substrate/frame/transaction-storage/src/mock.rs +++ b/substrate/frame/transaction-storage/src/mock.rs @@ -48,6 +48,7 @@ impl frame_system::Config for Test { type BlockLength = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = u64; type Hash = H256; type Hashing = BlakeTwo256; @@ -82,6 +83,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } impl pallet_transaction_storage::Config for Test { diff --git a/substrate/frame/treasury/src/tests.rs b/substrate/frame/treasury/src/tests.rs index ba45d5f6ff16..ef5fded42048 100644 --- a/substrate/frame/treasury/src/tests.rs +++ b/substrate/frame/treasury/src/tests.rs @@ -56,6 +56,7 @@ impl frame_system::Config for Test { type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = u128; // u64 is not enough to hold bytes used to generate bounty account @@ -87,6 +88,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } impl pallet_utility::Config for Test { diff --git a/substrate/frame/tx-pause/src/mock.rs b/substrate/frame/tx-pause/src/mock.rs index 60c5fc1eced5..0ce7aa5b808e 100644 --- a/substrate/frame/tx-pause/src/mock.rs +++ b/substrate/frame/tx-pause/src/mock.rs @@ -42,6 +42,7 @@ impl frame_system::Config for Test { type BlockLength = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = u64; type Hash = H256; type Hashing = BlakeTwo256; @@ -80,6 +81,7 @@ impl pallet_balances::Config for Test { type RuntimeHoldReason = RuntimeHoldReason; type MaxHolds = ConstU32<0>; type MaxFreezes = ConstU32<0>; + type RuntimeTask = RuntimeTask; } impl pallet_utility::Config for Test { diff --git a/substrate/frame/uniques/src/mock.rs b/substrate/frame/uniques/src/mock.rs index 5c44a7ed7a53..0aacdb0d45f0 100644 --- a/substrate/frame/uniques/src/mock.rs +++ b/substrate/frame/uniques/src/mock.rs @@ -46,6 +46,7 @@ impl frame_system::Config for Test { type BlockWeights = (); type BlockLength = (); type RuntimeOrigin = RuntimeOrigin; + type RuntimeTask = RuntimeTask; type RuntimeCall = RuntimeCall; type Nonce = u64; type Hash = H256; @@ -81,6 +82,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } impl Config for Test { diff --git a/substrate/frame/utility/src/tests.rs b/substrate/frame/utility/src/tests.rs index 183853c4e8ac..934ee8f6ce76 100644 --- a/substrate/frame/utility/src/tests.rs +++ b/substrate/frame/utility/src/tests.rs @@ -153,6 +153,7 @@ impl frame_system::Config for Test { type Nonce = u64; type Hash = H256; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; @@ -177,6 +178,7 @@ impl pallet_balances::Config for Test { type Balance = u64; type DustRemoval = (); type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type ExistentialDeposit = ConstU64<1>; type AccountStore = System; type WeightInfo = (); diff --git a/substrate/frame/vesting/src/mock.rs b/substrate/frame/vesting/src/mock.rs index fe1779475a69..d2bb06d8eaa7 100644 --- a/substrate/frame/vesting/src/mock.rs +++ b/substrate/frame/vesting/src/mock.rs @@ -46,6 +46,7 @@ impl frame_system::Config for Test { type BlockHashCount = ConstU64<250>; type BlockLength = (); type BlockWeights = (); + type RuntimeTask = RuntimeTask; type RuntimeCall = RuntimeCall; type DbWeight = (); type RuntimeEvent = RuntimeEvent; @@ -79,6 +80,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } parameter_types! { pub const MinVestedTransfer: u64 = 256 * 2; diff --git a/substrate/frame/whitelist/src/mock.rs b/substrate/frame/whitelist/src/mock.rs index d91f43b33af9..593d539b95b6 100644 --- a/substrate/frame/whitelist/src/mock.rs +++ b/substrate/frame/whitelist/src/mock.rs @@ -53,6 +53,7 @@ impl frame_system::Config for Test { type Nonce = u64; type Hash = H256; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; @@ -84,6 +85,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = (); type RuntimeHoldReason = (); type MaxHolds = (); + type RuntimeTask = RuntimeTask; } impl pallet_preimage::Config for Test { diff --git a/substrate/test-utils/runtime/src/lib.rs b/substrate/test-utils/runtime/src/lib.rs index b116c8556815..d342d2ae48a2 100644 --- a/substrate/test-utils/runtime/src/lib.rs +++ b/substrate/test-utils/runtime/src/lib.rs @@ -349,6 +349,7 @@ impl frame_system::pallet::Config for Runtime { type BlockLength = (); type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; + type RuntimeTask = RuntimeTask; type Nonce = Nonce; type Hash = H256; type Hashing = Hashing; @@ -391,6 +392,7 @@ impl pallet_balances::Config for Runtime { type Balance = Balance; type DustRemoval = (); type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = pallet_balances::weights::SubstrateWeight;