Skip to content

Commit 54ce95e

Browse files
gupnikkianenigma
andauthored
Adds example for dev_mode and updates doc (paritytech#13944)
* Adds example for dev_mode and updates doc * Addresses review comments * Update frame/examples/dev-mode/src/lib.rs Co-authored-by: Kian Paimani <[email protected]> * Addresses review comment --------- Co-authored-by: Kian Paimani <[email protected]>
1 parent 37f3d58 commit 54ce95e

File tree

7 files changed

+320
-0
lines changed

7 files changed

+320
-0
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
@@ -106,6 +106,7 @@ members = [
106106
"frame/election-provider-support/solution-type/fuzzer",
107107
"frame/examples/basic",
108108
"frame/examples/offchain-worker",
109+
"frame/examples/dev-mode",
109110
"frame/executive",
110111
"frame/nis",
111112
"frame/grandpa",

frame/examples/dev-mode/Cargo.toml

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
[package]
2+
name = "pallet-dev-mode"
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 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+
frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" }
20+
frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" }
21+
pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../balances" }
22+
sp-io = { version = "7.0.0", default-features = false, path = "../../../primitives/io" }
23+
sp-runtime = { version = "7.0.0", default-features = false, path = "../../../primitives/runtime" }
24+
sp-std = { version = "5.0.0", default-features = false, path = "../../../primitives/std" }
25+
26+
[dev-dependencies]
27+
sp-core = { version = "7.0.0", default-features = false, path = "../../../primitives/core" }
28+
29+
[features]
30+
default = ["std"]
31+
std = [
32+
"codec/std",
33+
"frame-support/std",
34+
"frame-system/std",
35+
"log/std",
36+
"pallet-balances/std",
37+
"scale-info/std",
38+
"sp-io/std",
39+
"sp-runtime/std",
40+
"sp-std/std",
41+
]
42+
try-runtime = ["frame-support/try-runtime"]

frame/examples/dev-mode/README.md

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!-- markdown-link-check-disable -->
2+
# Dev Mode Example Pallet
3+
4+
A simple example of a FRAME pallet demonstrating
5+
the ease of requirements for a pallet in dev mode.
6+
7+
Run `cargo doc --package pallet-dev-mode --open` to view this pallet's documentation.
8+
9+
**Dev mode is not meant to be used in production.**
10+
11+
License: MIT-0

frame/examples/dev-mode/src/lib.rs

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
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+
//! <!-- markdown-link-check-disable -->
19+
//! # Dev Mode Example Pallet
20+
//!
21+
//! A simple example of a FRAME pallet demonstrating
22+
//! the ease of requirements for a pallet in dev mode.
23+
//!
24+
//! Run `cargo doc --package pallet-dev-mode --open` to view this pallet's documentation.
25+
//!
26+
//! **Dev mode is not meant to be used in production.**
27+
28+
// Ensure we're `no_std` when compiling for Wasm.
29+
#![cfg_attr(not(feature = "std"), no_std)]
30+
31+
use frame_support::dispatch::DispatchResult;
32+
use frame_system::ensure_signed;
33+
34+
// Re-export pallet items so that they can be accessed from the crate namespace.
35+
pub use pallet::*;
36+
37+
#[cfg(test)]
38+
mod tests;
39+
40+
/// A type alias for the balance type from this pallet's point of view.
41+
type BalanceOf<T> = <T as pallet_balances::Config>::Balance;
42+
43+
/// Enable `dev_mode` for this pallet.
44+
#[frame_support::pallet(dev_mode)]
45+
pub mod pallet {
46+
use super::*;
47+
use frame_support::pallet_prelude::*;
48+
use frame_system::pallet_prelude::*;
49+
50+
#[pallet::config]
51+
pub trait Config: pallet_balances::Config + frame_system::Config {
52+
/// The overarching event type.
53+
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
54+
}
55+
56+
// Simple declaration of the `Pallet` type. It is placeholder we use to implement traits and
57+
// method.
58+
#[pallet::pallet]
59+
pub struct Pallet<T>(_);
60+
61+
#[pallet::call]
62+
impl<T: Config> Pallet<T> {
63+
#[pallet::call_index(0)]
64+
/// No need to define a `weight` attribute here because of `dev_mode`.
65+
pub fn add_dummy(origin: OriginFor<T>, id: T::AccountId) -> DispatchResult {
66+
ensure_root(origin)?;
67+
68+
if let Some(mut dummies) = Dummy::<T>::get() {
69+
dummies.push(id.clone());
70+
Dummy::<T>::set(Some(dummies));
71+
} else {
72+
Dummy::<T>::set(Some(vec![id.clone()]));
73+
}
74+
75+
// Let's deposit an event to let the outside world know this happened.
76+
Self::deposit_event(Event::AddDummy { account: id });
77+
78+
Ok(())
79+
}
80+
81+
#[pallet::call_index(1)]
82+
/// No need to define a `weight` attribute here because of `dev_mode`.
83+
pub fn set_bar(
84+
origin: OriginFor<T>,
85+
#[pallet::compact] new_value: T::Balance,
86+
) -> DispatchResult {
87+
let sender = ensure_signed(origin)?;
88+
89+
// Put the new value into storage.
90+
<Bar<T>>::insert(&sender, new_value);
91+
92+
Self::deposit_event(Event::SetBar { account: sender, balance: new_value });
93+
94+
Ok(())
95+
}
96+
}
97+
98+
#[pallet::event]
99+
#[pallet::generate_deposit(pub(super) fn deposit_event)]
100+
pub enum Event<T: Config> {
101+
AddDummy { account: T::AccountId },
102+
SetBar { account: T::AccountId, balance: BalanceOf<T> },
103+
}
104+
105+
/// The MEL requirement for bounded pallets is skipped by `dev_mode`.
106+
/// This means that all storages are marked as unbounded.
107+
/// This is equivalent to specifying `#[pallet::unbounded]` on this type definitions.
108+
/// When the dev_mode is removed, we would need to implement implement `MaxEncodedLen`.
109+
#[pallet::storage]
110+
pub type Dummy<T: Config> = StorageValue<_, Vec<T::AccountId>>;
111+
112+
/// The Hasher requirement is skipped by `dev_mode`. So, second parameter can be `_`
113+
/// and `Blake2_128Concat` is used as a default.
114+
/// When the dev_mode is removed, we would need to specify the hasher like so:
115+
/// `pub type Bar<T: Config> = StorageMap<_, Blake2_128Concat, T::AccountId, T::Balance>;`.
116+
#[pallet::storage]
117+
pub type Bar<T: Config> = StorageMap<_, _, T::AccountId, T::Balance>;
118+
}

frame/examples/dev-mode/src/tests.rs

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
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+
//! Tests for pallet-dev-mode.
19+
20+
use crate::*;
21+
use frame_support::{assert_ok, traits::ConstU64};
22+
use sp_core::H256;
23+
use sp_runtime::{
24+
testing::Header,
25+
traits::{BlakeTwo256, IdentityLookup},
26+
BuildStorage,
27+
};
28+
// Reexport crate as its pallet name for construct_runtime.
29+
use crate as pallet_dev_mode;
30+
31+
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
32+
type Block = frame_system::mocking::MockBlock<Test>;
33+
34+
// For testing the pallet, we construct a mock runtime.
35+
frame_support::construct_runtime!(
36+
pub enum Test where
37+
Block = Block,
38+
NodeBlock = Block,
39+
UncheckedExtrinsic = UncheckedExtrinsic,
40+
{
41+
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
42+
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
43+
Example: pallet_dev_mode::{Pallet, Call, Storage, Event<T>},
44+
}
45+
);
46+
47+
impl frame_system::Config for Test {
48+
type BaseCallFilter = frame_support::traits::Everything;
49+
type BlockWeights = ();
50+
type BlockLength = ();
51+
type DbWeight = ();
52+
type RuntimeOrigin = RuntimeOrigin;
53+
type Index = u64;
54+
type BlockNumber = u64;
55+
type Hash = H256;
56+
type RuntimeCall = RuntimeCall;
57+
type Hashing = BlakeTwo256;
58+
type AccountId = u64;
59+
type Lookup = IdentityLookup<Self::AccountId>;
60+
type Header = Header;
61+
type RuntimeEvent = RuntimeEvent;
62+
type BlockHashCount = ConstU64<250>;
63+
type Version = ();
64+
type PalletInfo = PalletInfo;
65+
type AccountData = pallet_balances::AccountData<u64>;
66+
type OnNewAccount = ();
67+
type OnKilledAccount = ();
68+
type SystemWeightInfo = ();
69+
type SS58Prefix = ();
70+
type OnSetCode = ();
71+
type MaxConsumers = frame_support::traits::ConstU32<16>;
72+
}
73+
74+
impl pallet_balances::Config for Test {
75+
type MaxLocks = ();
76+
type MaxReserves = ();
77+
type ReserveIdentifier = [u8; 8];
78+
type Balance = u64;
79+
type DustRemoval = ();
80+
type RuntimeEvent = RuntimeEvent;
81+
type ExistentialDeposit = ConstU64<1>;
82+
type AccountStore = System;
83+
type WeightInfo = ();
84+
type FreezeIdentifier = ();
85+
type MaxFreezes = ();
86+
type HoldIdentifier = ();
87+
type MaxHolds = ();
88+
}
89+
90+
impl Config for Test {
91+
type RuntimeEvent = RuntimeEvent;
92+
}
93+
94+
// This function basically just builds a genesis storage key/value store according to
95+
// our desired mockup.
96+
pub fn new_test_ext() -> sp_io::TestExternalities {
97+
let t = GenesisConfig {
98+
// We use default for brevity, but you can configure as desired if needed.
99+
system: Default::default(),
100+
balances: Default::default(),
101+
}
102+
.build_storage()
103+
.unwrap();
104+
t.into()
105+
}
106+
107+
#[test]
108+
fn it_works_for_optional_value() {
109+
new_test_ext().execute_with(|| {
110+
assert_eq!(Dummy::<Test>::get(), None);
111+
112+
let val1 = 42;
113+
assert_ok!(Example::add_dummy(RuntimeOrigin::root(), val1));
114+
assert_eq!(Dummy::<Test>::get(), Some(vec![val1]));
115+
116+
// Check that accumulate works when we have Some value in Dummy already.
117+
let val2 = 27;
118+
assert_ok!(Example::add_dummy(RuntimeOrigin::root(), val2));
119+
assert_eq!(Dummy::<Test>::get(), Some(vec![val1, val2]));
120+
});
121+
}
122+
123+
#[test]
124+
fn set_dummy_works() {
125+
new_test_ext().execute_with(|| {
126+
let test_val = 133;
127+
assert_ok!(Example::set_bar(RuntimeOrigin::signed(1), test_val.into()));
128+
assert_eq!(Bar::<Test>::get(1), Some(test_val));
129+
});
130+
}

frame/support/procedural/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,8 @@ pub fn construct_runtime(input: TokenStream) -> TokenStream {
465465
/// * All storages are marked as unbounded, meaning you do not need to implement `MaxEncodedLen` on
466466
/// storage types. This is equivalent to specifying `#[pallet::unbounded]` on all storage type
467467
/// definitions.
468+
/// * Storage hashers no longer need to be specified and can be replaced by `_`. In dev mode, these
469+
/// will be replaced by `Blake2_128Concat`.
468470
///
469471
/// Note that the `dev_mode` argument can only be supplied to the `#[pallet]` or
470472
/// `#[frame_support::pallet]` attribute macro that encloses your pallet module. This argument

0 commit comments

Comments
 (0)