mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-28 09:47:56 +00:00
002d9260f9
**Update:** Pushed additional changes based on the review comments. **This pull request fixes various spelling mistakes in this repository.** Most of the changes are contained in the first **3** commits: - `Fix spelling mistakes in comments and docs` - `Fix spelling mistakes in test names` - `Fix spelling mistakes in error messages, panic messages, logs and tracing` Other source code spelling mistakes are separated into individual commits for easier reviewing: - `Fix the spelling of 'authority'` - `Fix the spelling of 'REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY'` - `Fix the spelling of 'prev_enqueud_messages'` - `Fix the spelling of 'endpoint'` - `Fix the spelling of 'children'` - `Fix the spelling of 'PenpalSiblingSovereignAccount'` - `Fix the spelling of 'PenpalSudoAccount'` - `Fix the spelling of 'insufficient'` - `Fix the spelling of 'PalletXcmExtrinsicsBenchmark'` - `Fix the spelling of 'subtracted'` - `Fix the spelling of 'CandidatePendingAvailability'` - `Fix the spelling of 'exclusive'` - `Fix the spelling of 'until'` - `Fix the spelling of 'discriminator'` - `Fix the spelling of 'nonexistent'` - `Fix the spelling of 'subsystem'` - `Fix the spelling of 'indices'` - `Fix the spelling of 'committed'` - `Fix the spelling of 'topology'` - `Fix the spelling of 'response'` - `Fix the spelling of 'beneficiary'` - `Fix the spelling of 'formatted'` - `Fix the spelling of 'UNKNOWN_PROOF_REQUEST'` - `Fix the spelling of 'succeeded'` - `Fix the spelling of 'reopened'` - `Fix the spelling of 'proposer'` - `Fix the spelling of 'InstantiationNonce'` - `Fix the spelling of 'depositor'` - `Fix the spelling of 'expiration'` - `Fix the spelling of 'phantom'` - `Fix the spelling of 'AggregatedKeyValue'` - `Fix the spelling of 'randomness'` - `Fix the spelling of 'defendant'` - `Fix the spelling of 'AquaticMammal'` - `Fix the spelling of 'transactions'` - `Fix the spelling of 'PassingTracingSubscriber'` - `Fix the spelling of 'TxSignaturePayload'` - `Fix the spelling of 'versioning'` - `Fix the spelling of 'descendant'` - `Fix the spelling of 'overridden'` - `Fix the spelling of 'network'` Let me know if this structure is adequate. **Note:** The usage of the words `Merkle`, `Merkelize`, `Merklization`, `Merkelization`, `Merkleization`, is somewhat inconsistent but I left it as it is. ~~**Note:** In some places the term `Receival` is used to refer to message reception, IMO `Reception` is the correct word here, but I left it as it is.~~ ~~**Note:** In some places the term `Overlayed` is used instead of the more acceptable version `Overlaid` but I also left it as it is.~~ ~~**Note:** In some places the term `Applyable` is used instead of the correct version `Applicable` but I also left it as it is.~~ **Note:** Some usage of British vs American english e.g. `judgement` vs `judgment`, `initialise` vs `initialize`, `optimise` vs `optimize` etc. are both present in different places, but I suppose that's understandable given the number of contributors. ~~**Note:** There is a spelling mistake in `.github/CODEOWNERS` but it triggers errors in CI when I make changes to it, so I left it as it is.~~
271 lines
9.8 KiB
Rust
271 lines
9.8 KiB
Rust
// 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)]
|
|
#![deny(missing_docs)]
|
|
// Need to enable this one since we document feature-gated stuff.
|
|
#![allow(rustdoc::broken_intra_doc_links)]
|
|
|
|
//! # **⚠️ WARNING ⚠️**
|
|
//!
|
|
//! <br>
|
|
//! <b>THIS CRATE IS NOT AUDITED AND SHOULD NOT BE USED IN PRODUCTION.</b>
|
|
//! <br>
|
|
//!
|
|
//! # Parameters
|
|
//!
|
|
//! Allows to update configuration parameters at runtime.
|
|
//!
|
|
//! ## Pallet API
|
|
//!
|
|
//! This pallet exposes two APIs; one *inbound* side to update parameters, and one *outbound* side
|
|
//! to access said parameters. Parameters themselves are defined in the runtime config and will be
|
|
//! aggregated into an enum. Each parameter is addressed by a `key` and can have a default value.
|
|
//! This is not done by the pallet but through the [`frame_support::dynamic_params::dynamic_params`]
|
|
//! macro or alternatives.
|
|
//!
|
|
//! Note that this is incurring one storage read per access. This should not be a problem in most
|
|
//! cases but must be considered in weight-restrained code.
|
|
//!
|
|
//! ### Inbound
|
|
//!
|
|
//! The inbound side solely consists of the [`Pallet::set_parameter`] extrinsic to update the value
|
|
//! of a parameter. Each parameter can have their own admin origin as given by the
|
|
//! [`Config::AdminOrigin`].
|
|
//!
|
|
//! ### Outbound
|
|
//!
|
|
//! The outbound side is runtime facing for the most part. More general, it provides a `Get`
|
|
//! implementation and can be used in every spot where that is accepted. Two macros are in place:
|
|
//! [`frame_support::dynamic_params::define_parameters` and
|
|
//! [`frame_support::dynamic_params:dynamic_pallet_params`] to define and expose parameters in a
|
|
//! typed manner.
|
|
//!
|
|
//! See the [`pallet`] module for more information about the interfaces this pallet exposes,
|
|
//! including its configuration trait, dispatchables, storage items, events and errors.
|
|
//!
|
|
//! ## Overview
|
|
//!
|
|
//! This pallet is a good fit for updating parameters without a runtime upgrade. It is very handy to
|
|
//! not require a runtime upgrade for a simple parameter change since runtime upgrades require a lot
|
|
//! of diligence and always bear risks. It seems overkill to update the whole runtime for a simple
|
|
//! parameter change. This pallet allows for fine-grained control over who can update what.
|
|
//! The only down-side is that it trades off performance with convenience and should therefore only
|
|
//! be used in places where that is proven to be uncritical. Values that are rarely accessed but
|
|
//! change often would be a perfect fit.
|
|
//!
|
|
//! ### Example Configuration
|
|
//!
|
|
//! Here is an example of how to define some parameters, including their default values:
|
|
#![doc = docify::embed!("src/tests/mock.rs", dynamic_params)]
|
|
//!
|
|
//! A permissioned origin can be define on a per-key basis like this:
|
|
#![doc = docify::embed!("src/tests/mock.rs", custom_origin)]
|
|
//!
|
|
//! The pallet will also require a default value for benchmarking. Ideally this is the variant with
|
|
//! the longest encoded length. Although in either case the PoV benchmarking will take the worst
|
|
//! case over the whole enum.
|
|
#![doc = docify::embed!("src/tests/mock.rs", benchmarking_default)]
|
|
//!
|
|
//! Now the aggregated parameter needs to be injected into the pallet config:
|
|
#![doc = docify::embed!("src/tests/mock.rs", impl_config)]
|
|
//!
|
|
//! As last step, the parameters can now be used in other pallets 🙌
|
|
#![doc = docify::embed!("src/tests/mock.rs", usage)]
|
|
//!
|
|
//! ### Examples Usage
|
|
//!
|
|
//! Now to demonstrate how the values can be updated:
|
|
#![doc = docify::embed!("src/tests/unit.rs", set_parameters_example)]
|
|
//!
|
|
//! ## Low Level / Implementation Details
|
|
//!
|
|
//! The pallet stores the parameters in a storage map and implements the matching `Get<Value>` for
|
|
//! each `Key` type. The `Get` then accesses the `Parameters` map to retrieve the value. An event is
|
|
//! emitted every time that a value was updated. It is even emitted when the value is changed to the
|
|
//! same.
|
|
//!
|
|
//! The key and value types themselves are defined by macros and aggregated into a runtime wide
|
|
//! enum. This enum is then injected into the pallet. This allows it to be used without any changes
|
|
//! to the pallet that the parameter will be utilized by.
|
|
//!
|
|
//! ### Design Goals
|
|
//!
|
|
//! 1. Easy to update without runtime upgrade.
|
|
//! 2. Exposes metadata and docs for user convenience.
|
|
//! 3. Can be permissioned on a per-key base.
|
|
//!
|
|
//! ### Design
|
|
//!
|
|
//! 1. Everything is done at runtime without the need for `const` values. `Get` allows for this -
|
|
//! which is coincidentally an upside and a downside. 2. The types are defined through macros, which
|
|
//! allows to expose metadata and docs. 3. Access control is done through the `EnsureOriginWithArg`
|
|
//! trait, that allows to pass data along to the origin check. It gets passed in the key. The
|
|
//! implementor can then match on the key and the origin to decide whether the origin is
|
|
//! permissioned to set the value.
|
|
|
|
use frame_support::pallet_prelude::*;
|
|
use frame_system::pallet_prelude::*;
|
|
|
|
use frame_support::traits::{
|
|
dynamic_params::{AggregatedKeyValue, IntoKey, Key, RuntimeParameterStore, TryIntoKey},
|
|
EnsureOriginWithArg,
|
|
};
|
|
|
|
mod benchmarking;
|
|
#[cfg(test)]
|
|
mod tests;
|
|
mod weights;
|
|
|
|
pub use pallet::*;
|
|
pub use weights::WeightInfo;
|
|
|
|
/// The key type of a parameter.
|
|
type KeyOf<T> = <<T as Config>::RuntimeParameters as AggregatedKeyValue>::Key;
|
|
|
|
/// The value type of a parameter.
|
|
type ValueOf<T> = <<T as Config>::RuntimeParameters as AggregatedKeyValue>::Value;
|
|
|
|
#[frame_support::pallet]
|
|
pub mod pallet {
|
|
use super::*;
|
|
|
|
#[pallet::config(with_default)]
|
|
pub trait Config: frame_system::Config {
|
|
/// The overarching event type.
|
|
#[pallet::no_default_bounds]
|
|
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
|
|
|
|
/// The overarching KV type of the parameters.
|
|
///
|
|
/// Usually created by [`frame_support::dynamic_params`] or equivalent.
|
|
#[pallet::no_default_bounds]
|
|
type RuntimeParameters: AggregatedKeyValue;
|
|
|
|
/// The origin which may update a parameter.
|
|
///
|
|
/// The key of the parameter is passed in as second argument to allow for fine grained
|
|
/// control.
|
|
#[pallet::no_default_bounds]
|
|
type AdminOrigin: EnsureOriginWithArg<Self::RuntimeOrigin, KeyOf<Self>>;
|
|
|
|
/// Weight information for extrinsics in this module.
|
|
type WeightInfo: WeightInfo;
|
|
}
|
|
|
|
#[pallet::event]
|
|
#[pallet::generate_deposit(pub(crate) fn deposit_event)]
|
|
pub enum Event<T: Config> {
|
|
/// A Parameter was set.
|
|
///
|
|
/// Is also emitted when the value was not changed.
|
|
Updated {
|
|
/// The key that was updated.
|
|
key: <T::RuntimeParameters as AggregatedKeyValue>::Key,
|
|
/// The old value before this call.
|
|
old_value: Option<<T::RuntimeParameters as AggregatedKeyValue>::Value>,
|
|
/// The new value after this call.
|
|
new_value: Option<<T::RuntimeParameters as AggregatedKeyValue>::Value>,
|
|
},
|
|
}
|
|
|
|
/// Stored parameters.
|
|
#[pallet::storage]
|
|
pub type Parameters<T: Config> =
|
|
StorageMap<_, Blake2_128Concat, KeyOf<T>, ValueOf<T>, OptionQuery>;
|
|
|
|
#[pallet::pallet]
|
|
pub struct Pallet<T>(_);
|
|
|
|
#[pallet::call]
|
|
impl<T: Config> Pallet<T> {
|
|
/// Set the value of a parameter.
|
|
///
|
|
/// The dispatch origin of this call must be `AdminOrigin` for the given `key`. Values be
|
|
/// deleted by setting them to `None`.
|
|
#[pallet::call_index(0)]
|
|
#[pallet::weight(T::WeightInfo::set_parameter())]
|
|
pub fn set_parameter(
|
|
origin: OriginFor<T>,
|
|
key_value: T::RuntimeParameters,
|
|
) -> DispatchResult {
|
|
let (key, new) = key_value.into_parts();
|
|
T::AdminOrigin::ensure_origin(origin, &key)?;
|
|
|
|
let mut old = None;
|
|
Parameters::<T>::mutate(&key, |v| {
|
|
old = v.clone();
|
|
*v = new.clone();
|
|
});
|
|
|
|
Self::deposit_event(Event::Updated { key, old_value: old, new_value: new });
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
/// Default implementations of [`DefaultConfig`], which can be used to implement [`Config`].
|
|
pub mod config_preludes {
|
|
use super::*;
|
|
use frame_support::derive_impl;
|
|
|
|
/// A configuration for testing.
|
|
pub struct TestDefaultConfig;
|
|
|
|
#[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)]
|
|
impl frame_system::DefaultConfig for TestDefaultConfig {}
|
|
|
|
#[frame_support::register_default_impl(TestDefaultConfig)]
|
|
impl DefaultConfig for TestDefaultConfig {
|
|
#[inject_runtime_type]
|
|
type RuntimeEvent = ();
|
|
#[inject_runtime_type]
|
|
type RuntimeParameters = ();
|
|
|
|
type AdminOrigin = frame_support::traits::AsEnsureOriginWithArg<
|
|
frame_system::EnsureRoot<Self::AccountId>,
|
|
>;
|
|
|
|
type WeightInfo = ();
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T: Config> RuntimeParameterStore for Pallet<T> {
|
|
type AggregatedKeyValue = T::RuntimeParameters;
|
|
|
|
fn get<KV, K>(key: K) -> Option<K::Value>
|
|
where
|
|
KV: AggregatedKeyValue,
|
|
K: Key + Into<<KV as AggregatedKeyValue>::Key>,
|
|
<KV as AggregatedKeyValue>::Key: IntoKey<
|
|
<<Self as RuntimeParameterStore>::AggregatedKeyValue as AggregatedKeyValue>::Key,
|
|
>,
|
|
<<Self as RuntimeParameterStore>::AggregatedKeyValue as AggregatedKeyValue>::Value:
|
|
TryIntoKey<<KV as AggregatedKeyValue>::Value>,
|
|
<KV as AggregatedKeyValue>::Value: TryInto<K::WrappedValue>,
|
|
{
|
|
let key: <KV as AggregatedKeyValue>::Key = key.into();
|
|
let val = Parameters::<T>::get(key.into_key());
|
|
val.and_then(|v| {
|
|
let val: <KV as AggregatedKeyValue>::Value = v.try_into_key().ok()?;
|
|
let val: K::WrappedValue = val.try_into().ok()?;
|
|
let val = val.into();
|
|
Some(val)
|
|
})
|
|
}
|
|
}
|