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

Commit a779e4d

Browse files
gupnikcommand-botsam0x17
authored
[FRAME Core] Adds ability to split a pallet across multiple files (#13950)
* Initial setup * Updates macro_magic version and refactors accordingly * Removes unwrap from macro * Splits into multiple sections * Uses call_site to fix macro hygiene issue * Initial setup * Removes unnecessary changes * Moves template palet back * Updates cargo.lock * Moves BagsList inside mod * Comments access to internal functions for now * Updates tests * Uncomments code * Fixes test * Moves bags-list to separate crate * Initial setup * Removes bags-list changes * Fix structure * Minor update * Addresses review comment * Adds a couple of UI tests. More to be added * Adds err files * Adds test for no pallet * Adds doc * Updates versions * Adds benchmarking * Updates doc link * ".git/.scripts/commands/fmt/fmt.sh" * Minor update * Adds missing changes * ".git/.scripts/commands/fmt/fmt.sh" * Update frame/support/procedural/src/lib.rs Co-authored-by: Sam Johnson <[email protected]> * Addresses review comments * Addresses review comments * ".git/.scripts/commands/fmt/fmt.sh" * Update frame/support/procedural/src/lib.rs Co-authored-by: Sam Johnson <[email protected]> * Update frame/support/procedural/src/lib.rs Co-authored-by: Sam Johnson <[email protected]> * Update frame/support/procedural/src/lib.rs Co-authored-by: Sam Johnson <[email protected]> * Adds UI test for disambiguation * ".git/.scripts/commands/fmt/fmt.sh" * Makes clippy happy * ".git/.scripts/commands/fmt/fmt.sh" * Fixes frame support test * Fixes frame support test * Split items other than storage * Updates versions * Fixes some review comments * Addresses review comments * ".git/.scripts/commands/fmt/fmt.sh" * Updates docs * Adds experimental disclaimer * ".git/.scripts/commands/fmt/fmt.sh" * Update frame/support/test/tests/split_ui/no_section_found.rs Co-authored-by: Sam Johnson <[email protected]> * Addresses review comments * Fixes test --------- Co-authored-by: command-bot <> Co-authored-by: command-bot <[email protected]> Co-authored-by: Sam Johnson <[email protected]>
1 parent ecf7122 commit a779e4d

23 files changed

+837
-5
lines changed

Cargo.lock

+16
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ members = [
111111
"frame/examples/offchain-worker",
112112
"frame/examples/kitchensink",
113113
"frame/examples/dev-mode",
114+
"frame/examples/split",
114115
"frame/examples/default-config",
115116
"frame/executive",
116117
"frame/nis",

frame/examples/Cargo.toml

+4-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pallet-default-config-example = { default-features = false, path = "./default-co
1717
pallet-example-offchain-worker = { default-features = false, path = "./offchain-worker" }
1818
pallet-example-kitchensink = { default-features = false, path = "./kitchensink" }
1919
pallet-dev-mode = { default-features = false, path = "./dev-mode" }
20+
pallet-example-split = { default-features = false, path = "./split" }
2021

2122
[features]
2223
default = [ "std" ]
@@ -26,11 +27,13 @@ std = [
2627
"pallet-example-offchain-worker/std",
2728
"pallet-example-kitchensink/std",
2829
"pallet-dev-mode/std",
30+
"pallet-example-split/std",
2931
]
3032
try-runtime = [
3133
"pallet-example-basic/try-runtime",
3234
"pallet-default-config-example/try-runtime",
3335
"pallet-example-offchain-worker/try-runtime",
3436
"pallet-example-kitchensink/try-runtime",
3537
"pallet-dev-mode/try-runtime",
36-
]
38+
"pallet-example-split/try-runtime",
39+
]

frame/examples/split/Cargo.toml

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
[package]
2+
name = "pallet-example-split"
3+
version = "4.0.0-dev"
4+
authors = ["Parity Technologies <[email protected]>"]
5+
edition = "2021"
6+
license = "MIT-0"
7+
homepage = "https://substrate.io"
8+
repository = "https://github.com/paritytech/substrate/"
9+
description = "FRAME example splitted pallet"
10+
readme = "README.md"
11+
12+
[package.metadata.docs.rs]
13+
targets = ["x86_64-unknown-linux-gnu"]
14+
15+
[dependencies]
16+
codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false }
17+
log = { version = "0.4.17", default-features = false }
18+
scale-info = { version = "2.5.0", default-features = false, features = ["derive"] }
19+
20+
frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" }
21+
frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" }
22+
23+
sp-io = { version = "23.0.0", default-features = false, path = "../../../primitives/io" }
24+
sp-std = { version = "8.0.0", default-features = false, path = "../../../primitives/std" }
25+
26+
frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, path = "../../benchmarking" }
27+
28+
[dev-dependencies]
29+
sp-core = { version = "21.0.0", default-features = false, path = "../../../primitives/core" }
30+
31+
[features]
32+
default = ["std"]
33+
std = [
34+
"codec/std",
35+
"log/std",
36+
"scale-info/std",
37+
38+
"frame-support/std",
39+
"frame-system/std",
40+
41+
"sp-io/std",
42+
"sp-std/std",
43+
44+
"frame-benchmarking?/std",
45+
]
46+
runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"]
47+
try-runtime = ["frame-support/try-runtime"]

frame/examples/split/README.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!-- markdown-link-check-disable -->
2+
# Basic Example For Splitting A Pallet
3+
A simple example of a FRAME pallet demonstrating the ability to split sections across multiple
4+
files.
5+
6+
Note that this is purely experimental at this point.
7+
8+
Run `cargo doc --package pallet-example-split --open` to view this pallet's documentation.
9+
10+
License: MIT-0
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// This file is part of Substrate.
2+
3+
// Copyright (C) Parity Technologies (UK) Ltd.
4+
// SPDX-License-Identifier: Apache-2.0
5+
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
//! Benchmarking setup for pallet-example-split
19+
20+
// Only enable this module for benchmarking.
21+
#![cfg(feature = "runtime-benchmarks")]
22+
use super::*;
23+
24+
#[allow(unused)]
25+
use crate::Pallet as Template;
26+
use frame_benchmarking::v2::*;
27+
use frame_system::RawOrigin;
28+
29+
#[benchmarks]
30+
mod benchmarks {
31+
use super::*;
32+
33+
#[benchmark]
34+
fn do_something() {
35+
let value = 100u32.into();
36+
let caller: T::AccountId = whitelisted_caller();
37+
#[extrinsic_call]
38+
do_something(RawOrigin::Signed(caller), value);
39+
40+
assert_eq!(Something::<T>::get(), Some(value));
41+
}
42+
43+
#[benchmark]
44+
fn cause_error() {
45+
Something::<T>::put(100u32);
46+
let caller: T::AccountId = whitelisted_caller();
47+
#[extrinsic_call]
48+
cause_error(RawOrigin::Signed(caller));
49+
50+
assert_eq!(Something::<T>::get(), Some(101u32));
51+
}
52+
53+
impl_benchmark_test_suite!(Template, crate::mock::new_test_ext(), crate::mock::Test);
54+
}

frame/examples/split/src/events.rs

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// This file is part of Substrate.
2+
3+
// Copyright (C) Parity Technologies (UK) Ltd.
4+
// SPDX-License-Identifier: Apache-2.0
5+
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
use frame_support::pallet_macros::*;
19+
20+
/// A [`pallet_section`] that defines the events for a pallet.
21+
/// This can later be imported into the pallet using [`import_section`].
22+
#[pallet_section]
23+
mod events {
24+
#[pallet::event]
25+
#[pallet::generate_deposit(pub(super) fn deposit_event)]
26+
pub enum Event<T: Config> {
27+
/// Event documentation should end with an array that provides descriptive names for event
28+
/// parameters. [something, who]
29+
SomethingStored { something: u32, who: T::AccountId },
30+
}
31+
}

frame/examples/split/src/lib.rs

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
// This file is part of Substrate.
2+
3+
// Copyright (C) Parity Technologies (UK) Ltd.
4+
// SPDX-License-Identifier: Apache-2.0
5+
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
//! # Split Example Pallet
19+
//!
20+
//! **This pallet serves as an example and is not meant to be used in production.**
21+
//!
22+
//! A FRAME pallet demonstrating the ability to split sections across multiple files.
23+
//!
24+
//! Note that this is purely experimental at this point.
25+
26+
#![cfg_attr(not(feature = "std"), no_std)]
27+
28+
// Re-export pallet items so that they can be accessed from the crate namespace.
29+
pub use pallet::*;
30+
31+
#[cfg(test)]
32+
mod mock;
33+
34+
#[cfg(test)]
35+
mod tests;
36+
37+
#[cfg(feature = "runtime-benchmarks")]
38+
mod benchmarking;
39+
mod events;
40+
41+
pub mod weights;
42+
pub use weights::*;
43+
44+
use frame_support::pallet_macros::*;
45+
46+
/// Imports a [`pallet_section`] defined at [`events::events`].
47+
/// This brings the events defined in that section into the pallet's namespace.
48+
#[import_section(events::events)]
49+
#[frame_support::pallet]
50+
pub mod pallet {
51+
use super::*;
52+
use frame_support::pallet_prelude::*;
53+
use frame_system::pallet_prelude::*;
54+
55+
#[pallet::pallet]
56+
pub struct Pallet<T>(_);
57+
58+
/// Configure the pallet by specifying the parameters and types on which it depends.
59+
#[pallet::config]
60+
pub trait Config: frame_system::Config {
61+
/// Because this pallet emits events, it depends on the runtime's definition of an event.
62+
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
63+
/// Type representing the weight of this pallet
64+
type WeightInfo: WeightInfo;
65+
}
66+
67+
// The pallet's runtime storage items.
68+
#[pallet::storage]
69+
pub type Something<T> = StorageValue<_, u32>;
70+
71+
// Errors inform users that something went wrong.
72+
#[pallet::error]
73+
pub enum Error<T> {
74+
/// Error names should be descriptive.
75+
NoneValue,
76+
/// Errors should have helpful documentation associated with them.
77+
StorageOverflow,
78+
}
79+
80+
// Dispatchable functions allows users to interact with the pallet and invoke state changes.
81+
// These functions materialize as "extrinsics", which are often compared to transactions.
82+
// Dispatchable functions must be annotated with a weight and must return a DispatchResult.
83+
#[pallet::call]
84+
impl<T: Config> Pallet<T> {
85+
/// An example dispatchable that takes a singles value as a parameter, writes the value to
86+
/// storage and emits an event. This function must be dispatched by a signed extrinsic.
87+
#[pallet::call_index(0)]
88+
#[pallet::weight(T::WeightInfo::do_something())]
89+
pub fn do_something(origin: OriginFor<T>, something: u32) -> DispatchResult {
90+
// Check that the extrinsic was signed and get the signer.
91+
// This function will return an error if the extrinsic is not signed.
92+
let who = ensure_signed(origin)?;
93+
94+
// Update storage.
95+
<Something<T>>::put(something);
96+
97+
// Emit an event.
98+
Self::deposit_event(Event::SomethingStored { something, who });
99+
// Return a successful DispatchResultWithPostInfo
100+
Ok(())
101+
}
102+
103+
/// An example dispatchable that may throw a custom error.
104+
#[pallet::call_index(1)]
105+
#[pallet::weight(T::WeightInfo::cause_error())]
106+
pub fn cause_error(origin: OriginFor<T>) -> DispatchResult {
107+
let _who = ensure_signed(origin)?;
108+
109+
// Read a value from storage.
110+
match <Something<T>>::get() {
111+
// Return an error if the value has not been set.
112+
None => return Err(Error::<T>::NoneValue.into()),
113+
Some(old) => {
114+
// Increment the value read from storage; will error in the event of overflow.
115+
let new = old.checked_add(1).ok_or(Error::<T>::StorageOverflow)?;
116+
// Update the value in storage with the incremented result.
117+
<Something<T>>::put(new);
118+
Ok(())
119+
},
120+
}
121+
}
122+
}
123+
}

frame/examples/split/src/mock.rs

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// This file is part of Substrate.
2+
3+
// Copyright (C) Parity Technologies (UK) Ltd.
4+
// SPDX-License-Identifier: Apache-2.0
5+
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
use crate as pallet_template;
19+
use frame_support::derive_impl;
20+
21+
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
22+
type Block = frame_system::mocking::MockBlock<Test>;
23+
24+
// Configure a mock runtime to test the pallet.
25+
frame_support::construct_runtime!(
26+
pub enum Test where
27+
Block = Block,
28+
NodeBlock = Block,
29+
UncheckedExtrinsic = UncheckedExtrinsic,
30+
{
31+
System: frame_system,
32+
TemplatePallet: pallet_template,
33+
}
34+
);
35+
36+
/// Using a default config for [`frame_system`] in tests. See `default-config` example for more
37+
/// details.
38+
#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
39+
impl frame_system::Config for Test {
40+
type BaseCallFilter = frame_support::traits::Everything;
41+
type RuntimeOrigin = RuntimeOrigin;
42+
type RuntimeCall = RuntimeCall;
43+
type RuntimeEvent = RuntimeEvent;
44+
type PalletInfo = PalletInfo;
45+
type OnSetCode = ();
46+
}
47+
48+
impl pallet_template::Config for Test {
49+
type RuntimeEvent = RuntimeEvent;
50+
type WeightInfo = ();
51+
}
52+
53+
// Build genesis storage according to the mock runtime.
54+
pub fn new_test_ext() -> sp_io::TestExternalities {
55+
frame_system::GenesisConfig::default().build_storage::<Test>().unwrap().into()
56+
}

0 commit comments

Comments
 (0)