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

FRAME: General System for Recognizing and Executing Service Work #14329

Draft
wants to merge 49 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
71e16aa
initial API for Task trait
sam0x17 Jun 8, 2023
9a70eaf
Merge remote-tracking branch 'origin/master' into sam-tasks
sam0x17 Jun 16, 2023
01e3bbe
remove lifetime as per basti's suggestion
sam0x17 Jun 16, 2023
28f13cf
bound Task on FullCodec
sam0x17 Jun 19, 2023
f22054b
fix imports
sam0x17 Jun 19, 2023
4682e6f
set task_index to const
sam0x17 Jul 4, 2023
389131c
change to an associated const
sam0x17 Jul 5, 2023
4756ade
Merge remote-tracking branch 'origin/master' into sam-tasks
sam0x17 Jul 10, 2023
19f6ef6
compiles using wrapper PalletTask<T: Config> trait ... WIP
sam0x17 Jul 12, 2023
f967a80
example task impl using a wrapper task possibly working (compiles)
sam0x17 Jul 12, 2023
777c0c8
Merge remote-tracking branch 'origin/master' into sam-tasks
sam0x17 Jul 17, 2023
e07c25a
use generic ExampleTask<T: Config>
sam0x17 Jul 17, 2023
b4c57ba
use frame_support::Never
sam0x17 Jul 17, 2023
32bbd4e
refactor to be more like Call
sam0x17 Jul 20, 2023
ba54c4e
first attempt at implementing do_task
sam0x17 Jul 20, 2023
acf0d27
bind T and Task by TypeInfo
sam0x17 Jul 24, 2023
2b1083a
Merge remote-tracking branch 'origin/master' into sam-tasks
sam0x17 Aug 2, 2023
ddc2e9d
add parsing for task-related attributes
sam0x17 Aug 3, 2023
f7ca7d5
add tests for task related attribute macros
sam0x17 Aug 3, 2023
4d30f6c
first stab at validate_unsigned within tasks_example pallet
sam0x17 Aug 4, 2023
34e0990
add comments
sam0x17 Aug 4, 2023
f29f0a0
clean up
sam0x17 Aug 4, 2023
36dae43
improve scaffold a bit
sam0x17 Aug 4, 2023
d20f312
rename inner `#[pallet::tasks()]` to #[pallet::task_list(..)]` to red…
sam0x17 Aug 4, 2023
e7092b7
Merge remote-tracking branch 'origin/master' into sam-tasks
sam0x17 Aug 7, 2023
af70bd9
add Task as a composite enum
sam0x17 Aug 7, 2023
260a715
hook up RuntimeTask to construct_runtime
sam0x17 Aug 8, 2023
a0fc4c8
do_task system pallet extrinsic WIP (solved RuntimeTask issue)
sam0x17 Aug 9, 2023
49353a7
do_task extrinsic on system pallet done
sam0x17 Aug 10, 2023
4ac3fc7
fix comment
sam0x17 Aug 10, 2023
b26602d
suppress warning
sam0x17 Aug 10, 2023
a40a03e
context information on #[pallet::error] = bad
sam0x17 Aug 10, 2023
131766f
very granular task-related events (will probably reduce this)
sam0x17 Aug 10, 2023
6be3ce3
clean up old code
sam0x17 Aug 14, 2023
b553a3b
remove TaskInvalid event based on feedback
sam0x17 Aug 14, 2023
45e69f8
add AggregatedTask trait which we can use in RuntimeTask
sam0x17 Aug 14, 2023
af5f469
add tasks-example pallet to construct_runtime temporarily for testing
sam0x17 Aug 14, 2023
de82efe
refine tasks re-export paths
sam0x17 Aug 14, 2023
923cfc8
inject `RuntimeTask` into all construct_runtime!'s
sam0x17 Aug 14, 2023
0f62953
clean up
sam0x17 Aug 14, 2023
b704c87
AggregatedTask impl WIP
sam0x17 Aug 14, 2023
77f5629
include RuntimeTask in tasks-example
sam0x17 Aug 14, 2023
d74cc95
aggregation almost working, issue with `decl.find_part("Task")`
sam0x17 Aug 14, 2023
5f6e016
identify that there is an issue with decl.find_part WRT tasks
sam0x17 Aug 14, 2023
f823fc4
try Task not Tasks
sam0x17 Aug 14, 2023
b551c34
reference Task and other pallet parts in the runtime
sam0x17 Aug 16, 2023
cfda435
fix handling of tasks in expand_tt_default_parts
sam0x17 Aug 17, 2023
da2a524
item_enum
sam0x17 Aug 17, 2023
fa2b824
Fixes build
gupnik Aug 17, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ members = [
"frame/examples/dev-mode",
"frame/examples/split",
"frame/examples/default-config",
"frame/examples/tasks-example",
"frame/executive",
"frame/nis",
"frame/grandpa",
Expand Down
1 change: 1 addition & 0 deletions bin/node-template/pallets/template/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions bin/node-template/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<AccountId, ()>;
/// The type for storing how many extrinsics an account has signed.
Expand Down
1 change: 1 addition & 0 deletions bin/node/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ pallet-transaction-storage = { version = "4.0.0-dev", default-features = false,
pallet-uniques = { version = "4.0.0-dev", default-features = false, path = "../../../frame/uniques" }
pallet-vesting = { version = "4.0.0-dev", default-features = false, path = "../../../frame/vesting" }
pallet-whitelist = { version = "4.0.0-dev", default-features = false, path = "../../../frame/whitelist" }
tasks-example = { version = "4.0.0-dev", path = '../../../frame/examples/tasks-example', default-features = false }

[build-dependencies]
substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-builder", optional = true }
Expand Down
9 changes: 9 additions & 0 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,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;
Expand Down Expand Up @@ -224,6 +225,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;
Expand All @@ -245,6 +247,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;
Expand Down Expand Up @@ -1946,6 +1953,7 @@ construct_runtime!(
MessageQueue: pallet_message_queue,
Pov: frame_benchmarking_pallet_pov,
Statement: pallet_statement,
TasksExample: tasks_example,
}
);

Expand Down Expand Up @@ -2031,6 +2039,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]
Expand Down
38 changes: 38 additions & 0 deletions frame/examples/tasks-example/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[package]
name = "tasks-example"
version = "4.0.0-dev"
authors = ["Parity Technologies <admin@parity.io>"]
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"]
179 changes: 179 additions & 0 deletions frame/examples/tasks-example/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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<T: Config> {
Increment,
Decrement,
#[doc(hidden)]
#[codec(skip)]
__Ignore(PhantomData<T>, frame_support::Never),
}

// this can be auto-generated from the macros and will always be the same
impl<T: Config> core::fmt::Debug for Task<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Task").field("value", self).finish()
sam0x17 marked this conversation as resolved.
Show resolved Hide resolved
}
}

// 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<T> {
InvalidTask,
ValueOverflow,
ValueUnderflow,
}

// this will be auto-generated from `#[pallet::tasks]`
impl<T: Config> frame_support::traits::Task for Task<T>
where
T: TypeInfo,
{
type Enumeration = sp_std::vec::IntoIter<Task<T>>;

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::<T>::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::<T>::get().unwrap_or_default();
if value >= 255 {
Err(Error::<T>::ValueOverflow.into())
} else {
let new_val = value.checked_add(1).ok_or(Error::<T>::ValueOverflow)?;
Value::<T>::put(new_val);
Pallet::<T>::deposit_event(Event::Incremented { new_val });
Ok(())
}
},
Task::Decrement => {
// Get the value and check if it can be decremented
let value = Value::<T>::get().unwrap_or_default();
if value == 0 {
Err(Error::<T>::ValueUnderflow.into())
} else {
let new_val = value.checked_sub(1).ok_or(Error::<T>::ValueUnderflow)?;
Value::<T>::put(new_val);
Pallet::<T>::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<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
type RuntimeTask: AggregatedTask;
}

#[pallet::pallet]
pub struct Pallet<T>(_);

#[pallet::storage]
#[pallet::getter(fn value)]
pub type Value<T: Config> = StorageValue<_, u8>;

#[pallet::call]
impl<T: Config> Pallet<T>
where
T: TypeInfo,
{
pub fn increment(origin: OriginFor<T>) -> DispatchResult {
ensure_root(origin)?;

// Increment the value and emit an event
let new_val = Value::<T>::get().unwrap().checked_add(1).ok_or("Value overflow")?;
Value::<T>::put(new_val);
Self::deposit_event(Event::Incremented { new_val });

Ok(())
}

pub fn decrement(origin: OriginFor<T>) -> DispatchResult {
ensure_root(origin)?;

// Decrement the value and emit an event
let new_val = Value::<T>::get().unwrap().checked_sub(1).ok_or("Value underflow")?;
Value::<T>::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<T>, task: Task<T>) -> DispatchResult {
use frame_support::traits::Task;
ensure_root(origin)?;
if task.is_valid() {
task.run()
} else {
Err(Error::<T>::InvalidTask.into())
}
}
}

#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
Incremented { new_val: u8 },
Decremented { new_val: u8 },
}
}
2 changes: 2 additions & 0 deletions frame/support/procedural/src/construct_runtime/expand/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ mod metadata;
mod origin;
mod outer_enums;
mod slash_reason;
mod task;
mod unsigned;

pub use call::expand_outer_dispatch;
Expand All @@ -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;
Loading
Loading