Skip to content

Commit e53ebd8

Browse files
ggwpezgupnikkianenigma
authored
[FRAME] Parameters pallet (#2061)
Closes #169 Fork of the `orml-parameters-pallet` as introduced by open-web3-stack/open-runtime-module-library#927 (cc @xlc) It greatly changes how the macros work, but keeps the pallet the same. The downside of my code is now that it does only support constant keys in the form of types, not value-bearing keys. I think this is an acceptable trade off, give that it can be used by *any* pallet without any changes. The pallet allows to dynamically set parameters that can be used in pallet configs while also restricting the updating on a per-key basis. The rust-docs contains a complete example. Changes: - Add `parameters-pallet` - Use in the kitchensink as demonstration - Add experimental attribute to define dynamic params in the runtime. - Adding a bunch of traits to `frame_support::traits::dynamic_params` that can be re-used by the ORML macros ## Example First to define the parameters in the runtime file. The syntax is very explicit about the codec index and errors if there is no. ```rust #[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::<Runtime>))] pub mod dynamic_params { use super::*; #[dynamic_pallet_params] #[codec(index = 0)] pub mod storage { /// Configures the base deposit of storing some data. #[codec(index = 0)] pub static BaseDeposit: Balance = 1 * DOLLARS; /// Configures the per-byte deposit of storing some data. #[codec(index = 1)] pub static ByteDeposit: Balance = 1 * CENTS; } #[dynamic_pallet_params] #[codec(index = 1)] pub mod contracts { #[codec(index = 0)] pub static DepositPerItem: Balance = deposit(1, 0); #[codec(index = 1)] pub static DepositPerByte: Balance = deposit(0, 1); } } ``` Then the pallet is configured with the aggregate: ```rust impl pallet_parameters::Config for Runtime { type AggregratedKeyValue = RuntimeParameters; type AdminOrigin = EnsureRootWithSuccess<AccountId, ConstBool<true>>; ... } ``` And then the parameters can be used in a pallet config: ```rust impl pallet_preimage::Config for Runtime { type DepositBase = dynamic_params::storage::DepositBase; } ``` A custom origin an be defined like this: ```rust pub struct DynamicParametersManagerOrigin; impl EnsureOriginWithArg<RuntimeOrigin, RuntimeParametersKey> for DynamicParametersManagerOrigin { type Success = (); fn try_origin( origin: RuntimeOrigin, key: &RuntimeParametersKey, ) -> Result<Self::Success, RuntimeOrigin> { match key { RuntimeParametersKey::Storage(_) => { frame_system::ensure_root(origin.clone()).map_err(|_| origin)?; return Ok(()) }, RuntimeParametersKey::Contract(_) => { frame_system::ensure_root(origin.clone()).map_err(|_| origin)?; return Ok(()) }, } } #[cfg(feature = "runtime-benchmarks")] fn try_successful_origin(_key: &RuntimeParametersKey) -> Result<RuntimeOrigin, ()> { Ok(RuntimeOrigin::Root) } } ``` --------- Signed-off-by: Oliver Tale-Yazdi <[email protected]> Co-authored-by: Nikhil Gupta <[email protected]> Co-authored-by: Kian Paimani <[email protected]> Co-authored-by: command-bot <>
1 parent aac07af commit e53ebd8

File tree

21 files changed

+2017
-18
lines changed

21 files changed

+2017
-18
lines changed

Cargo.lock

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ members = [
366366
"substrate/frame/offences/benchmarking",
367367
"substrate/frame/paged-list",
368368
"substrate/frame/paged-list/fuzzer",
369+
"substrate/frame/parameters",
369370
"substrate/frame/preimage",
370371
"substrate/frame/proxy",
371372
"substrate/frame/ranked-collective",

prdoc/pr_2061.prdoc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
2+
# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
3+
4+
title: Add Parameters Pallet
5+
6+
doc:
7+
- audience: Runtime Dev
8+
description: |
9+
Adds `pallet-parameters` that allows to have parameters for pallet configs that dynamically change at runtime. Allows to be permissioned on a per-key basis and is compatible with ORML macros.
10+
11+
crates:
12+
- name: "pallet-parameters"
13+
- name: "frame-support"
14+
- name: "frame-support-procedural"

substrate/bin/node/runtime/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ pallet-vesting = { path = "../../../frame/vesting", default-features = false }
142142
pallet-whitelist = { path = "../../../frame/whitelist", default-features = false }
143143
pallet-tx-pause = { path = "../../../frame/tx-pause", default-features = false }
144144
pallet-safe-mode = { path = "../../../frame/safe-mode", default-features = false }
145+
pallet-parameters = { path = "../../../frame/parameters", default-features = false }
145146

146147
[build-dependencies]
147148
substrate-wasm-builder = { path = "../../../utils/wasm-builder", optional = true }
@@ -209,6 +210,7 @@ std = [
209210
"pallet-nomination-pools/std",
210211
"pallet-offences-benchmarking?/std",
211212
"pallet-offences/std",
213+
"pallet-parameters/std",
212214
"pallet-preimage/std",
213215
"pallet-proxy/std",
214216
"pallet-ranked-collective/std",
@@ -310,6 +312,7 @@ runtime-benchmarks = [
310312
"pallet-nomination-pools/runtime-benchmarks",
311313
"pallet-offences-benchmarking/runtime-benchmarks",
312314
"pallet-offences/runtime-benchmarks",
315+
"pallet-parameters/runtime-benchmarks",
313316
"pallet-preimage/runtime-benchmarks",
314317
"pallet-proxy/runtime-benchmarks",
315318
"pallet-ranked-collective/runtime-benchmarks",
@@ -386,6 +389,7 @@ try-runtime = [
386389
"pallet-nis/try-runtime",
387390
"pallet-nomination-pools/try-runtime",
388391
"pallet-offences/try-runtime",
392+
"pallet-parameters/try-runtime",
389393
"pallet-preimage/try-runtime",
390394
"pallet-proxy/try-runtime",
391395
"pallet-ranked-collective/try-runtime",

substrate/bin/node/runtime/src/lib.rs

Lines changed: 89 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use frame_election_provider_support::{
3030
use frame_support::{
3131
construct_runtime, derive_impl,
3232
dispatch::DispatchClass,
33+
dynamic_params::{dynamic_pallet_params, dynamic_params},
3334
genesis_builder_helper::{build_config, create_default_config},
3435
instances::{Instance1, Instance2},
3536
ord_parameter_types,
@@ -44,9 +45,9 @@ use frame_support::{
4445
GetSalary, PayFromAccount,
4546
},
4647
AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU16, ConstU32, Contains, Currency,
47-
EitherOfDiverse, EqualPrivilegeOnly, Imbalance, InsideBoth, InstanceFilter,
48-
KeyOwnerProofSystem, LinearStoragePrice, LockIdentifier, Nothing, OnUnbalanced,
49-
WithdrawReasons,
48+
EitherOfDiverse, EnsureOriginWithArg, EqualPrivilegeOnly, Imbalance, InsideBoth,
49+
InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, LockIdentifier, Nothing,
50+
OnUnbalanced, WithdrawReasons,
5051
},
5152
weights::{
5253
constants::{
@@ -457,9 +458,6 @@ impl pallet_glutton::Config for Runtime {
457458
}
458459

459460
parameter_types! {
460-
pub const PreimageBaseDeposit: Balance = 1 * DOLLARS;
461-
// One cent: $10,000 / MB
462-
pub const PreimageByteDeposit: Balance = 1 * CENTS;
463461
pub const PreimageHoldReason: RuntimeHoldReason = RuntimeHoldReason::Preimage(pallet_preimage::HoldReason::Preimage);
464462
}
465463

@@ -472,7 +470,11 @@ impl pallet_preimage::Config for Runtime {
472470
AccountId,
473471
Balances,
474472
PreimageHoldReason,
475-
LinearStoragePrice<PreimageBaseDeposit, PreimageByteDeposit, Balance>,
473+
LinearStoragePrice<
474+
dynamic_params::storage::BaseDeposit,
475+
dynamic_params::storage::ByteDeposit,
476+
Balance,
477+
>,
476478
>;
477479
}
478480

@@ -1326,9 +1328,6 @@ impl pallet_tips::Config for Runtime {
13261328
}
13271329

13281330
parameter_types! {
1329-
pub const DepositPerItem: Balance = deposit(1, 0);
1330-
pub const DepositPerByte: Balance = deposit(0, 1);
1331-
pub const DefaultDepositLimit: Balance = deposit(1024, 1024 * 1024);
13321331
pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();
13331332
pub CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(30);
13341333
}
@@ -1346,9 +1345,9 @@ impl pallet_contracts::Config for Runtime {
13461345
/// change because that would break already deployed contracts. The `Call` structure itself
13471346
/// is not allowed to change the indices of existing pallets, too.
13481347
type CallFilter = Nothing;
1349-
type DepositPerItem = DepositPerItem;
1350-
type DepositPerByte = DepositPerByte;
1351-
type DefaultDepositLimit = DefaultDepositLimit;
1348+
type DepositPerItem = dynamic_params::contracts::DepositPerItem;
1349+
type DepositPerByte = dynamic_params::contracts::DepositPerByte;
1350+
type DefaultDepositLimit = dynamic_params::contracts::DefaultDepositLimit;
13521351
type CallStack = [pallet_contracts::Frame<Self>; 5];
13531352
type WeightPrice = pallet_transaction_payment::Pallet<Self>;
13541353
type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;
@@ -2088,6 +2087,81 @@ impl pallet_mixnet::Config for Runtime {
20882087
type MinMixnodes = ConstU32<7>; // Low to allow small testing networks
20892088
}
20902089

2090+
/// Dynamic parameters that can be changed at runtime through the
2091+
/// `pallet_parameters::set_parameter`.
2092+
#[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::<Runtime>)]
2093+
pub mod dynamic_params {
2094+
use super::*;
2095+
2096+
#[dynamic_pallet_params]
2097+
#[codec(index = 0)]
2098+
pub mod storage {
2099+
/// Configures the base deposit of storing some data.
2100+
#[codec(index = 0)]
2101+
pub static BaseDeposit: Balance = 1 * DOLLARS;
2102+
2103+
/// Configures the per-byte deposit of storing some data.
2104+
#[codec(index = 1)]
2105+
pub static ByteDeposit: Balance = 1 * CENTS;
2106+
}
2107+
2108+
#[dynamic_pallet_params]
2109+
#[codec(index = 1)]
2110+
pub mod contracts {
2111+
#[codec(index = 0)]
2112+
pub static DepositPerItem: Balance = deposit(1, 0);
2113+
2114+
#[codec(index = 1)]
2115+
pub static DepositPerByte: Balance = deposit(0, 1);
2116+
2117+
#[codec(index = 2)]
2118+
pub static DefaultDepositLimit: Balance = deposit(1024, 1024 * 1024);
2119+
}
2120+
}
2121+
2122+
#[cfg(feature = "runtime-benchmarks")]
2123+
impl Default for RuntimeParameters {
2124+
fn default() -> Self {
2125+
RuntimeParameters::Storage(dynamic_params::storage::Parameters::BaseDeposit(
2126+
dynamic_params::storage::BaseDeposit,
2127+
Some(1 * DOLLARS),
2128+
))
2129+
}
2130+
}
2131+
2132+
pub struct DynamicParametersManagerOrigin;
2133+
impl EnsureOriginWithArg<RuntimeOrigin, RuntimeParametersKey> for DynamicParametersManagerOrigin {
2134+
type Success = ();
2135+
2136+
fn try_origin(
2137+
origin: RuntimeOrigin,
2138+
key: &RuntimeParametersKey,
2139+
) -> Result<Self::Success, RuntimeOrigin> {
2140+
match key {
2141+
RuntimeParametersKey::Storage(_) => {
2142+
frame_system::ensure_root(origin.clone()).map_err(|_| origin)?;
2143+
return Ok(())
2144+
},
2145+
RuntimeParametersKey::Contract(_) => {
2146+
frame_system::ensure_root(origin.clone()).map_err(|_| origin)?;
2147+
return Ok(())
2148+
},
2149+
}
2150+
}
2151+
2152+
#[cfg(feature = "runtime-benchmarks")]
2153+
fn try_successful_origin(_key: &RuntimeParametersKey) -> Result<RuntimeOrigin, ()> {
2154+
Ok(RuntimeOrigin::root())
2155+
}
2156+
}
2157+
2158+
impl pallet_parameters::Config for Runtime {
2159+
type RuntimeParameters = RuntimeParameters;
2160+
type RuntimeEvent = RuntimeEvent;
2161+
type AdminOrigin = DynamicParametersManagerOrigin;
2162+
type WeightInfo = ();
2163+
}
2164+
20912165
construct_runtime!(
20922166
pub enum Runtime {
20932167
System: frame_system,
@@ -2169,6 +2243,7 @@ construct_runtime!(
21692243
Broker: pallet_broker,
21702244
TasksExample: pallet_example_tasks,
21712245
Mixnet: pallet_mixnet,
2246+
Parameters: pallet_parameters,
21722247
SkipFeelessPayment: pallet_skip_feeless_payment,
21732248
}
21742249
);
@@ -2288,6 +2363,7 @@ mod benches {
22882363
[pallet_elections_phragmen, Elections]
22892364
[pallet_fast_unstake, FastUnstake]
22902365
[pallet_nis, Nis]
2366+
[pallet_parameters, Parameters]
22912367
[pallet_grandpa, Grandpa]
22922368
[pallet_identity, Identity]
22932369
[pallet_im_online, ImOnline]

substrate/frame/examples/kitchensink/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ codec = { package = "parity-scale-codec", version = "3.6.1", default-features =
2020
log = { version = "0.4.17", default-features = false }
2121
scale-info = { version = "2.10.0", default-features = false, features = ["derive"] }
2222

23-
frame-support = { path = "../../support", default-features = false }
23+
frame-support = { path = "../../support", default-features = false, features = ["experimental"] }
2424
frame-system = { path = "../../system", default-features = false }
2525

2626
sp-io = { path = "../../../primitives/io", default-features = false }

substrate/frame/parameters/Cargo.toml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
[package]
2+
name = "pallet-parameters"
3+
description = "Pallet to store and configure parameters."
4+
repository.workspace = true
5+
license = "Apache-2.0"
6+
version = "0.0.1"
7+
authors = ["Acala Developers", "Parity Technologies <[email protected]>"]
8+
edition.workspace = true
9+
10+
[dependencies]
11+
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["max-encoded-len"] }
12+
scale-info = { version = "2.1.2", default-features = false, features = ["derive"] }
13+
paste = { version = "1.0.14", default-features = false }
14+
serde = { version = "1.0.188", features = ["derive"], optional = true }
15+
docify = "0.2.5"
16+
17+
frame-support = { path = "../support", default-features = false, features = ["experimental"] }
18+
frame-system = { path = "../system", default-features = false }
19+
sp-core = { path = "../../primitives/core", default-features = false }
20+
sp-runtime = { path = "../../primitives/runtime", default-features = false }
21+
sp-std = { path = "../../primitives/std", default-features = false }
22+
frame-benchmarking = { path = "../benchmarking", default-features = false, optional = true }
23+
24+
[dev-dependencies]
25+
sp-core = { path = "../../primitives/core", features = ["std"] }
26+
sp-io = { path = "../../primitives/io", features = ["std"] }
27+
pallet-example-basic = { path = "../examples/basic", features = ["std"] }
28+
pallet-balances = { path = "../balances", features = ["std"] }
29+
30+
[features]
31+
default = ["std"]
32+
std = [
33+
"codec/std",
34+
"frame-benchmarking?/std",
35+
"frame-support/std",
36+
"frame-system/std",
37+
"scale-info/std",
38+
"serde",
39+
"sp-core/std",
40+
"sp-runtime/std",
41+
"sp-std/std",
42+
]
43+
runtime-benchmarks = [
44+
"frame-benchmarking/runtime-benchmarks",
45+
"frame-support/runtime-benchmarks",
46+
"frame-system/runtime-benchmarks",
47+
"pallet-balances/runtime-benchmarks",
48+
"pallet-example-basic/runtime-benchmarks",
49+
"sp-runtime/runtime-benchmarks",
50+
]
51+
try-runtime = [
52+
"frame-support/try-runtime",
53+
"frame-system/try-runtime",
54+
"pallet-balances/try-runtime",
55+
"pallet-example-basic/try-runtime",
56+
"sp-runtime/try-runtime",
57+
]
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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+
//! Parameters pallet benchmarking.
19+
20+
#![cfg(feature = "runtime-benchmarks")]
21+
22+
use super::*;
23+
#[cfg(test)]
24+
use crate::Pallet as Parameters;
25+
26+
use frame_benchmarking::v2::*;
27+
28+
#[benchmarks(where T::RuntimeParameters: Default)]
29+
mod benchmarks {
30+
use super::*;
31+
32+
#[benchmark]
33+
fn set_parameter() -> Result<(), BenchmarkError> {
34+
let kv = T::RuntimeParameters::default();
35+
let k = kv.clone().into_parts().0;
36+
37+
let origin =
38+
T::AdminOrigin::try_successful_origin(&k).map_err(|_| BenchmarkError::Weightless)?;
39+
40+
#[extrinsic_call]
41+
_(origin as T::RuntimeOrigin, kv);
42+
43+
Ok(())
44+
}
45+
46+
impl_benchmark_test_suite! {
47+
Parameters,
48+
crate::tests::mock::new_test_ext(),
49+
crate::tests::mock::Runtime,
50+
}
51+
}

0 commit comments

Comments
 (0)