mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 21:41:12 +00:00
[FRAME] Warn on unchecked weight witness (#1818)
Adds a warning to FRAME pallets when a function argument that starts
with `_` is used in the weight formula.
This is in most cases an error since the weight witness needs to be
checked.
Example:
```rust
#[pallet::call_index(0)]
#[pallet::weight(T::SystemWeightInfo::remark(_remark.len() as u32))]
pub fn remark(_origin: OriginFor<T>, _remark: Vec<u8>) -> DispatchResultWithPostInfo {
Ok(().into())
}
```
Produces this warning:
```pre
warning: use of deprecated constant `pallet::warnings::UncheckedWeightWitness_0::_w`:
It is deprecated to not check weight witness data.
Please instead ensure that all witness data for weight calculation is checked before usage.
For more info see:
<https://github.com/paritytech/polkadot-sdk/pull/1818>
--> substrate/frame/system/src/lib.rs:424:40
|
424 | pub fn remark(_origin: OriginFor<T>, _remark: Vec<u8>) -> DispatchResultWithPostInfo {
| ^^^^^^^
|
= note: `#[warn(deprecated)]` on by default
```
Can be suppressed like this, since in this case it is legit:
```rust
#[pallet::call_index(0)]
#[pallet::weight(T::SystemWeightInfo::remark(remark.len() as u32))]
pub fn remark(_origin: OriginFor<T>, remark: Vec<u8>) -> DispatchResultWithPostInfo {
let _ = remark; // We dont need to check the weight witness.
Ok(().into())
}
```
Changes:
- Add warning on uncheded weight witness
- Respect `subkeys` limit in `System::kill_prefix`
- Fix HRMP pallet and other warnings
- Update`proc_macro_warning` dependency
- Delete random folder `substrate/src/src` 🙈
- Adding Prdoc
---------
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
e3c97e4860
commit
64877492c5
Generated
+4
-4
@@ -13327,9 +13327,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-warning"
|
||||
version = "0.4.2"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d1eaa7fa0aa1929ffdf7eeb6eac234dde6268914a14ad44d23521ab6a9b258e"
|
||||
checksum = "9b698b0b09d40e9b7c1a47b132d66a8b54bcd20583d9b6d06e4535e383b4405c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -13338,9 +13338,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.67"
|
||||
version = "1.0.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
|
||||
checksum = "5b1106fec09662ec6dd98ccac0f81cef56984d0b49f75c92d8cbad76e20c005c"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
@@ -554,14 +554,26 @@ pub mod pallet {
|
||||
///
|
||||
/// Origin must be the `ChannelManager`.
|
||||
#[pallet::call_index(3)]
|
||||
#[pallet::weight(<T as Config>::WeightInfo::force_clean_hrmp(*_inbound, *_outbound))]
|
||||
#[pallet::weight(<T as Config>::WeightInfo::force_clean_hrmp(*num_inbound, *num_outbound))]
|
||||
pub fn force_clean_hrmp(
|
||||
origin: OriginFor<T>,
|
||||
para: ParaId,
|
||||
_inbound: u32,
|
||||
_outbound: u32,
|
||||
num_inbound: u32,
|
||||
num_outbound: u32,
|
||||
) -> DispatchResult {
|
||||
T::ChannelManager::ensure_origin(origin)?;
|
||||
|
||||
ensure!(
|
||||
HrmpIngressChannelsIndex::<T>::decode_len(para).unwrap_or_default() <=
|
||||
num_inbound as usize,
|
||||
Error::<T>::WrongWitness
|
||||
);
|
||||
ensure!(
|
||||
HrmpEgressChannelsIndex::<T>::decode_len(para).unwrap_or_default() <=
|
||||
num_outbound as usize,
|
||||
Error::<T>::WrongWitness
|
||||
);
|
||||
|
||||
Self::clean_hrmp_after_outgoing(¶);
|
||||
Ok(())
|
||||
}
|
||||
@@ -575,9 +587,16 @@ pub mod pallet {
|
||||
///
|
||||
/// Origin must be the `ChannelManager`.
|
||||
#[pallet::call_index(4)]
|
||||
#[pallet::weight(<T as Config>::WeightInfo::force_process_hrmp_open(*_channels))]
|
||||
pub fn force_process_hrmp_open(origin: OriginFor<T>, _channels: u32) -> DispatchResult {
|
||||
#[pallet::weight(<T as Config>::WeightInfo::force_process_hrmp_open(*channels))]
|
||||
pub fn force_process_hrmp_open(origin: OriginFor<T>, channels: u32) -> DispatchResult {
|
||||
T::ChannelManager::ensure_origin(origin)?;
|
||||
|
||||
ensure!(
|
||||
HrmpOpenChannelRequestsList::<T>::decode_len().unwrap_or_default() as u32 <=
|
||||
channels,
|
||||
Error::<T>::WrongWitness
|
||||
);
|
||||
|
||||
let host_config = configuration::Pallet::<T>::config();
|
||||
Self::process_hrmp_open_channel_requests(&host_config);
|
||||
Ok(())
|
||||
@@ -592,9 +611,16 @@ pub mod pallet {
|
||||
///
|
||||
/// Origin must be the `ChannelManager`.
|
||||
#[pallet::call_index(5)]
|
||||
#[pallet::weight(<T as Config>::WeightInfo::force_process_hrmp_close(*_channels))]
|
||||
pub fn force_process_hrmp_close(origin: OriginFor<T>, _channels: u32) -> DispatchResult {
|
||||
#[pallet::weight(<T as Config>::WeightInfo::force_process_hrmp_close(*channels))]
|
||||
pub fn force_process_hrmp_close(origin: OriginFor<T>, channels: u32) -> DispatchResult {
|
||||
T::ChannelManager::ensure_origin(origin)?;
|
||||
|
||||
ensure!(
|
||||
HrmpCloseChannelRequestsList::<T>::decode_len().unwrap_or_default() as u32 <=
|
||||
channels,
|
||||
Error::<T>::WrongWitness
|
||||
);
|
||||
|
||||
Self::process_hrmp_close_channel_requests();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
title: FRAME pallets warning for unchecked weight witness
|
||||
|
||||
doc:
|
||||
- audience: Core Dev
|
||||
description: |
|
||||
FRAME pallets now emit a warning when a call uses a function argument that starts with an underscore in its weight declaration.
|
||||
|
||||
migrations:
|
||||
db: [ ]
|
||||
runtime: [ ]
|
||||
|
||||
host_functions: []
|
||||
|
||||
crates:
|
||||
- name: "frame-support-procedural"
|
||||
semver: minor
|
||||
@@ -379,7 +379,7 @@ benchmarks! {
|
||||
let root = RawOrigin::Root;
|
||||
}: _(root, v, d)
|
||||
verify {
|
||||
assert_eq!(<Voting<T>>::iter().count() as u32, 0);
|
||||
assert_eq!(<Voting<T>>::iter().count() as u32, v - d);
|
||||
}
|
||||
|
||||
election_phragmen {
|
||||
|
||||
@@ -591,15 +591,18 @@ pub mod pallet {
|
||||
/// ## Complexity
|
||||
/// - Check is_defunct_voter() details.
|
||||
#[pallet::call_index(5)]
|
||||
#[pallet::weight(T::WeightInfo::clean_defunct_voters(*_num_voters, *_num_defunct))]
|
||||
#[pallet::weight(T::WeightInfo::clean_defunct_voters(*num_voters, *num_defunct))]
|
||||
pub fn clean_defunct_voters(
|
||||
origin: OriginFor<T>,
|
||||
_num_voters: u32,
|
||||
_num_defunct: u32,
|
||||
num_voters: u32,
|
||||
num_defunct: u32,
|
||||
) -> DispatchResult {
|
||||
let _ = ensure_root(origin)?;
|
||||
|
||||
<Voting<T>>::iter()
|
||||
.take(num_voters as usize)
|
||||
.filter(|(_, x)| Self::is_defunct_voter(&x.votes))
|
||||
.take(num_defunct as usize)
|
||||
.for_each(|(dv, _)| Self::do_remove_voter(&dv));
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -29,7 +29,7 @@ use sp_runtime::Perbill;
|
||||
|
||||
pub use pallet::*;
|
||||
|
||||
#[frame_support::pallet]
|
||||
#[frame_support::pallet(dev_mode)]
|
||||
pub mod pallet {
|
||||
use super::*;
|
||||
use frame_support::pallet_prelude::*;
|
||||
|
||||
@@ -204,14 +204,15 @@ pub mod pallet {
|
||||
/// ## Complexity
|
||||
/// - O(1).
|
||||
#[pallet::call_index(1)]
|
||||
#[pallet::weight((*_weight, call.get_dispatch_info().class))]
|
||||
#[pallet::weight((*weight, call.get_dispatch_info().class))]
|
||||
pub fn sudo_unchecked_weight(
|
||||
origin: OriginFor<T>,
|
||||
call: Box<<T as Config>::RuntimeCall>,
|
||||
_weight: Weight,
|
||||
weight: Weight,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
// This is a public call, so we ensure that the origin is some signed account.
|
||||
let sender = ensure_signed(origin)?;
|
||||
let _ = weight; // We don't check the weight witness since it is a root call.
|
||||
ensure!(Self::key().map_or(false, |k| sender == k), Error::<T>::RequireSudo);
|
||||
|
||||
let res = call.dispatch_bypass_filter(frame_system::RawOrigin::Root.into());
|
||||
|
||||
@@ -23,7 +23,7 @@ proc-macro2 = "1.0.56"
|
||||
quote = "1.0.28"
|
||||
syn = { version = "2.0.38", features = ["full"] }
|
||||
frame-support-procedural-tools = { path = "tools" }
|
||||
proc-macro-warning = { version = "0.4.2", default-features = false }
|
||||
proc-macro-warning = { version = "1.0.0", default-features = false }
|
||||
macro_magic = { version = "0.4.2", features = ["proc_support"] }
|
||||
expander = "2.0.0"
|
||||
sp-core-hashing = { path = "../../../primitives/core/hashing" }
|
||||
|
||||
@@ -414,7 +414,7 @@ fn construct_runtime_final_expansion(
|
||||
)
|
||||
.help_links(&["https://github.com/paritytech/substrate/pull/14437"])
|
||||
.span(where_section.span)
|
||||
.build(),
|
||||
.build_or_panic(),
|
||||
)
|
||||
});
|
||||
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
|
||||
use crate::{
|
||||
pallet::{
|
||||
expand::warnings::{weight_constant_warning, weight_witness_warning},
|
||||
parse::call::{CallVariantDef, CallWeightDef},
|
||||
Def,
|
||||
},
|
||||
COUNTER,
|
||||
};
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use proc_macro_warning::Warning;
|
||||
use quote::{quote, ToTokens};
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
@@ -68,7 +70,7 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
continue
|
||||
}
|
||||
|
||||
let warning = proc_macro_warning::Warning::new_deprecated("ImplicitCallIndex")
|
||||
let warning = Warning::new_deprecated("ImplicitCallIndex")
|
||||
.index(call_index_warnings.len())
|
||||
.old("use implicit call indices")
|
||||
.new("ensure that all calls have a `pallet::call_index` attribute or put the pallet into `dev` mode")
|
||||
@@ -77,7 +79,7 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
"https://github.com/paritytech/substrate/pull/11381"
|
||||
])
|
||||
.span(method.name.span())
|
||||
.build();
|
||||
.build_or_panic();
|
||||
call_index_warnings.push(warning);
|
||||
}
|
||||
|
||||
@@ -86,18 +88,12 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
for method in &methods {
|
||||
match &method.weight {
|
||||
CallWeightDef::DevModeDefault => fn_weight.push(syn::parse_quote!(0)),
|
||||
CallWeightDef::Immediate(e @ syn::Expr::Lit(lit)) if !def.dev_mode => {
|
||||
let warning = proc_macro_warning::Warning::new_deprecated("ConstantWeight")
|
||||
.index(weight_warnings.len())
|
||||
.old("use hard-coded constant as call weight")
|
||||
.new("benchmark all calls or put the pallet into `dev` mode")
|
||||
.help_link("https://github.com/paritytech/substrate/pull/13798")
|
||||
.span(lit.span())
|
||||
.build();
|
||||
weight_warnings.push(warning);
|
||||
CallWeightDef::Immediate(e) => {
|
||||
weight_constant_warning(e, def.dev_mode, &mut weight_warnings);
|
||||
weight_witness_warning(method, def.dev_mode, &mut weight_warnings);
|
||||
|
||||
fn_weight.push(e.into_token_stream());
|
||||
},
|
||||
CallWeightDef::Immediate(e) => fn_weight.push(e.into_token_stream()),
|
||||
CallWeightDef::Inherited => {
|
||||
let pallet_weight = def
|
||||
.call
|
||||
|
||||
@@ -34,6 +34,7 @@ mod store_trait;
|
||||
mod tt_default_parts;
|
||||
mod type_value;
|
||||
mod validate_unsigned;
|
||||
mod warnings;
|
||||
|
||||
use crate::pallet::Def;
|
||||
use quote::ToTokens;
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
// 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.
|
||||
|
||||
//! Generates warnings for undesirable pallet code.
|
||||
|
||||
use crate::pallet::parse::call::{CallVariantDef, CallWeightDef};
|
||||
use proc_macro_warning::Warning;
|
||||
use syn::{
|
||||
spanned::Spanned,
|
||||
visit::{self, Visit},
|
||||
};
|
||||
|
||||
/// Warn if any of the call arguments starts with a underscore and is used in a weight formula.
|
||||
pub(crate) fn weight_witness_warning(
|
||||
method: &CallVariantDef,
|
||||
dev_mode: bool,
|
||||
warnings: &mut Vec<Warning>,
|
||||
) {
|
||||
if dev_mode {
|
||||
return
|
||||
}
|
||||
let CallWeightDef::Immediate(w) = &method.weight else {
|
||||
return;
|
||||
};
|
||||
|
||||
let partial_warning = Warning::new_deprecated("UncheckedWeightWitness")
|
||||
.old("not check weight witness data")
|
||||
.new("ensure that all witness data for weight calculation is checked before usage")
|
||||
.help_link("https://github.com/paritytech/polkadot-sdk/pull/1818");
|
||||
|
||||
for (_, arg_ident, _) in method.args.iter() {
|
||||
if !arg_ident.to_string().starts_with('_') || !contains_ident(w.clone(), &arg_ident) {
|
||||
continue
|
||||
}
|
||||
|
||||
let warning = partial_warning
|
||||
.clone()
|
||||
.index(warnings.len())
|
||||
.span(arg_ident.span())
|
||||
.build_or_panic();
|
||||
|
||||
warnings.push(warning);
|
||||
}
|
||||
}
|
||||
|
||||
/// Warn if the weight is a constant and the pallet not in `dev_mode`.
|
||||
pub(crate) fn weight_constant_warning(
|
||||
weight: &syn::Expr,
|
||||
dev_mode: bool,
|
||||
warnings: &mut Vec<Warning>,
|
||||
) {
|
||||
if dev_mode {
|
||||
return
|
||||
}
|
||||
let syn::Expr::Lit(lit) = weight else {
|
||||
return;
|
||||
};
|
||||
|
||||
let warning = Warning::new_deprecated("ConstantWeight")
|
||||
.index(warnings.len())
|
||||
.old("use hard-coded constant as call weight")
|
||||
.new("benchmark all calls or put the pallet into `dev` mode")
|
||||
.help_link("https://github.com/paritytech/substrate/pull/13798")
|
||||
.span(lit.span())
|
||||
.build_or_panic();
|
||||
|
||||
warnings.push(warning);
|
||||
}
|
||||
|
||||
/// Returns whether `expr` contains `ident`.
|
||||
fn contains_ident(mut expr: syn::Expr, ident: &syn::Ident) -> bool {
|
||||
struct ContainsIdent {
|
||||
ident: syn::Ident,
|
||||
found: bool,
|
||||
}
|
||||
|
||||
impl<'a> Visit<'a> for ContainsIdent {
|
||||
fn visit_ident(&mut self, i: &syn::Ident) {
|
||||
if *i == self.ident {
|
||||
self.found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut visitor = ContainsIdent { ident: ident.clone(), found: false };
|
||||
visit::visit_expr(&mut visitor, &mut expr);
|
||||
visitor.found
|
||||
}
|
||||
@@ -210,12 +210,13 @@ pub mod pallet {
|
||||
{
|
||||
/// Doc comment put in metadata
|
||||
#[pallet::call_index(0)]
|
||||
#[pallet::weight(Weight::from_parts(*_foo as u64, 0))]
|
||||
#[pallet::weight(Weight::from_parts(*foo as u64, 0))]
|
||||
pub fn foo(
|
||||
origin: OriginFor<T>,
|
||||
#[pallet::compact] _foo: u32,
|
||||
#[pallet::compact] foo: u32,
|
||||
_bar: u32,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
let _ = foo;
|
||||
let _ = T::AccountId::from(SomeType1); // Test for where clause
|
||||
let _ = T::AccountId::from(SomeType3); // Test for where clause
|
||||
let _ = origin;
|
||||
|
||||
@@ -87,12 +87,13 @@ pub mod pallet {
|
||||
impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
/// Doc comment put in metadata
|
||||
#[pallet::call_index(0)]
|
||||
#[pallet::weight(Weight::from_parts(*_foo as u64, 0))]
|
||||
#[pallet::weight(Weight::from_parts(*foo as u64, 0))]
|
||||
pub fn foo(
|
||||
origin: OriginFor<T>,
|
||||
#[pallet::compact] _foo: u32,
|
||||
#[pallet::compact] foo: u32,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
let _ = origin;
|
||||
let _ = foo;
|
||||
Self::deposit_event(Event::Something(3));
|
||||
Ok(().into())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// 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.
|
||||
|
||||
#[frame_support::pallet]
|
||||
mod pallet {
|
||||
use frame_support::pallet_prelude::DispatchResult;
|
||||
use frame_system::pallet_prelude::OriginFor;
|
||||
|
||||
#[pallet::config]
|
||||
pub trait Config: frame_system::Config {}
|
||||
|
||||
#[pallet::pallet]
|
||||
pub struct Pallet<T>(core::marker::PhantomData<T>);
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {
|
||||
#[pallet::call_index(0)]
|
||||
#[pallet::weight(*_unused)]
|
||||
pub fn foo(_: OriginFor<T>, _unused: u64) -> DispatchResult { Ok(()) }
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
error: use of deprecated constant `pallet::warnings::UncheckedWeightWitness_0::_w`:
|
||||
It is deprecated to not check weight witness data.
|
||||
Please instead ensure that all witness data for weight calculation is checked before usage.
|
||||
|
||||
For more info see:
|
||||
<https://github.com/paritytech/polkadot-sdk/pull/1818>
|
||||
--> tests/pallet_ui/call_weight_unchecked_warning.rs:33:31
|
||||
|
|
||||
33 | pub fn foo(_: OriginFor<T>, _unused: u64) -> DispatchResult { Ok(()) }
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: `-D deprecated` implied by `-D warnings`
|
||||
@@ -420,8 +420,9 @@ pub mod pallet {
|
||||
///
|
||||
/// Can be executed by every `origin`.
|
||||
#[pallet::call_index(0)]
|
||||
#[pallet::weight(T::SystemWeightInfo::remark(_remark.len() as u32))]
|
||||
pub fn remark(_origin: OriginFor<T>, _remark: Vec<u8>) -> DispatchResultWithPostInfo {
|
||||
#[pallet::weight(T::SystemWeightInfo::remark(remark.len() as u32))]
|
||||
pub fn remark(_origin: OriginFor<T>, remark: Vec<u8>) -> DispatchResultWithPostInfo {
|
||||
let _ = remark; // No need to check the weight witness.
|
||||
Ok(().into())
|
||||
}
|
||||
|
||||
@@ -495,16 +496,16 @@ pub mod pallet {
|
||||
/// the prefix we are removing to accurately calculate the weight of this function.
|
||||
#[pallet::call_index(6)]
|
||||
#[pallet::weight((
|
||||
T::SystemWeightInfo::kill_prefix(_subkeys.saturating_add(1)),
|
||||
T::SystemWeightInfo::kill_prefix(subkeys.saturating_add(1)),
|
||||
DispatchClass::Operational,
|
||||
))]
|
||||
pub fn kill_prefix(
|
||||
origin: OriginFor<T>,
|
||||
prefix: Key,
|
||||
_subkeys: u32,
|
||||
subkeys: u32,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
ensure_root(origin)?;
|
||||
let _ = storage::unhashed::clear_prefix(&prefix, None, None);
|
||||
let _ = storage::unhashed::clear_prefix(&prefix, Some(subkeys), None);
|
||||
Ok(().into())
|
||||
}
|
||||
|
||||
|
||||
@@ -479,13 +479,15 @@ pub mod pallet {
|
||||
///
|
||||
/// The dispatch origin for this call must be _Root_.
|
||||
#[pallet::call_index(5)]
|
||||
#[pallet::weight((*_weight, call.get_dispatch_info().class))]
|
||||
#[pallet::weight((*weight, call.get_dispatch_info().class))]
|
||||
pub fn with_weight(
|
||||
origin: OriginFor<T>,
|
||||
call: Box<<T as Config>::RuntimeCall>,
|
||||
_weight: Weight,
|
||||
weight: Weight,
|
||||
) -> DispatchResult {
|
||||
ensure_root(origin)?;
|
||||
let _ = weight; // Explicitly don't check the the weight witness.
|
||||
|
||||
let res = call.dispatch_bypass_filter(frame_system::RawOrigin::Root.into());
|
||||
res.map(|_| ()).map_err(|e| e.error)
|
||||
}
|
||||
|
||||
@@ -1,297 +0,0 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! # Substrate
|
||||
//!
|
||||
//! Substrate is a Rust framework for building blockchains in a modular and extensible way. While in
|
||||
//! itself un-opinionated, it is the main engine behind the Polkadot ecosystem.
|
||||
//!
|
||||
//! [![github]](https://github.com/paritytech/substrate/) - [![polkadot]](https://polkadot.network)
|
||||
//!
|
||||
//! This crate in itself does not contain any code and is just meant ot be a documentation hub for
|
||||
//! substrate-based crates.
|
||||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
//! Substrate approaches blockchain development with an acknowledgement of a few self-evident
|
||||
//! truths:
|
||||
//!
|
||||
//! 1. Society and technology evolves.
|
||||
//! 2. Humans are fallible.
|
||||
//!
|
||||
//! This, specifically, makes the task of designing a correct, safe and long-lasting blockchain
|
||||
//! system hard.
|
||||
//!
|
||||
//! Nonetheless, in order to achieve this goal, substrate embraces the following:
|
||||
//!
|
||||
//! 1. Use of **Rust** as a modern, and safe programming language, which limits human error through
|
||||
//! various means, most notably memory safety.
|
||||
//! 2. Substrate is written from the ground-up with a generic, modular and extensible design. This
|
||||
//! ensures that software components can be easily swapped and upgraded. Examples of this is
|
||||
//! multiple consensus mechanisms provided by Substrate, as listed below.
|
||||
//! 3. Lastly, the final blockchain system created with the above properties needs to be
|
||||
//! upgradeable. In order to achieve this, Substrate is designed as a meta-protocol, whereby the
|
||||
//! application logic of the blockchain (called "Runtime") is encoded as a Wasm blob, and is
|
||||
//! stored onchain. The rest of the system (called "Client") acts as the executor of the Wasm
|
||||
//! blob.
|
||||
//!
|
||||
//! In essence, the meta-protocol of all Substrate based chains is the "Runtime as Wasm blob"
|
||||
//! accord. This enables the Runtime to become inherently upgradeable (without forks). The upgrade
|
||||
//! is merely a matter of the Wasm blob being changed in the chain state, which is, in principle,
|
||||
//! same as updating an account's balance.
|
||||
//!
|
||||
//! To learn more about the substrate architecture using some visuals, see [`substrate_diagram`].
|
||||
//!
|
||||
//! `FRAME`, Substrate's default runtime development library takes the above even further by
|
||||
//! embracing a declarative programming model whereby correctness is enhanced and the system is
|
||||
//! highly configurable through parameterization.
|
||||
//!
|
||||
//! All in all, this design enables all substrate-based chains to achieve forkless, self-enacting
|
||||
//! upgrades out of the box. Combined with governance abilities that are shipped with `FRAME`, this
|
||||
//! enables a chain to survive the test of time.
|
||||
//!
|
||||
//! ## How to Get Stared
|
||||
//!
|
||||
//! Most developers want to leave the client side code as-is, and focus on the runtime. To do so,
|
||||
//! look into the [`frame_support`] crate, which is the entry point crate into runtime development
|
||||
//! with FRAME.
|
||||
//!
|
||||
//! > Side note, it is entirely possible to craft a substrate-based runtime without FRAME, an
|
||||
//! > example of which can be found [here](https://github.com/JoshOrndorff/frameless-node-template).
|
||||
//!
|
||||
//! In more broad terms, the following avenues exist into developing with substrate:
|
||||
//!
|
||||
//! * **Templates**: A number of substrate-based templates exist and they can be used for various
|
||||
//! purposes, with zero to little additional code needed. All of these templates contain runtimes
|
||||
//! that are highly configurable and are likely suitable for basic needs.
|
||||
//! * `FRAME`: If need, one can customize that runtime even further, by using `FRAME` and developing
|
||||
//! custom modules.
|
||||
//! * **Core**: To the contrary, some developers may want to customize the client side software to
|
||||
//! achieve novel goals such as a new consensus engine, or a new database backend. While
|
||||
//! Substrate's main configurability is in the runtime, the client is also highly generic and can
|
||||
//! be customized to a great extent.
|
||||
//!
|
||||
//! ## Structure
|
||||
//!
|
||||
//! Substrate is a massive cargo workspace with hundreds of crates, therefore it is useful to know
|
||||
//! how to navigate its crates.
|
||||
//!
|
||||
//! In broad terms, it is divided into three categories:
|
||||
//!
|
||||
//! * `sc-*` (short for *substrate-client*) crates, located under `./client` folder. These are all
|
||||
//! the client crates. Notable examples are crates such as [`sc-network`], various consensus
|
||||
//! crates, [`sc-rpc-api`] and [`sc-client-db`], all of which are expected to reside in the client
|
||||
//! side.
|
||||
//! * `sp-*` (short for *substrate-primitives*) crates, located under `./primitives` folder. These
|
||||
//! are the traits that glue the client and runtime together, but are not opinionated about what
|
||||
//! framework is using for building the runtime. Notable examples are [`sp-api`] and [`sp-io`],
|
||||
//! which form the communication bridge between the client and runtime, as explained in
|
||||
//! [`substrate_diagram`].
|
||||
//! * `pallet-*` and `frame-*` crates, located under `./frame` folder. These are the crates related
|
||||
//! to FRAME. See [`frame_support`] for more information.
|
||||
//!
|
||||
//! ### Wasm Build
|
||||
//!
|
||||
//! Many of the Substrate crates, such as entire `sp-*`, need to compile to both Wasm (when a Wasm
|
||||
//! runtime is being generated) and native (for example, when testing). To achieve this, Substrate
|
||||
//! follows the convention of the Rust community, and uses a `feature = "std"` to signify that a
|
||||
//! crate is being built with the standard library, and is built for native. Otherwise, it is built
|
||||
//! for `no_std`.
|
||||
//!
|
||||
//! This can be summarized in `#![cfg_attr(not(feature = "std"), no_std)]`, which you can often find
|
||||
//! in any Substrate-based runtime.
|
||||
//!
|
||||
//! Substrate-based runtimes use [`substrate-wasm-builder`] in their `build.rs` to automatically
|
||||
//! build their Wasm files as a part of normal build commandsOnce built, the wasm file is placed in
|
||||
//! `./target/{debug|release}/wbuild/{runtime_name}.wasm`.
|
||||
//!
|
||||
//! ### Binaries
|
||||
//!
|
||||
//! Multiple binaries are shipped with substrate, the most important of which are located in the
|
||||
//! `./bin` folder.
|
||||
//!
|
||||
//! * [`node`] is an extensive substrate node that contains the superset of all runtime and client
|
||||
//! side features. The corresponding runtime, called [`kitchensink_runtime`] contains all of the
|
||||
//! modules that are provided with `FRAME`. This node and runtime is only used for testing and
|
||||
//! demonstration.
|
||||
//! * [`chain-spec-builder`]: Utility to build more detailed chain-specs for the aforementioned
|
||||
//! node. Other projects typically contain a `build-spec` subcommand that does the same.
|
||||
//! * [`node-template`]: a template node that contains a minimal set of features and can act as a
|
||||
//! starting point of a project.
|
||||
//! * [`subkey`]: Substrate's key management utility.
|
||||
//!
|
||||
//! ### Anatomy of a Binary Crate
|
||||
//!
|
||||
//! From the above, [`node`] and [`node-template`] are essentially blueprints of a substrate-based
|
||||
//! project, as the name of the latter is implying. Each substrate-based project typically contains
|
||||
//! the following:
|
||||
//!
|
||||
//! * Under `./runtime`, a `./runtime/src/lib.rs` which is the top level runtime amalgamator file.
|
||||
//! This file typically contains the [`frame_support::construct_runtime`] macro, which is the
|
||||
//! final definition of a runtime.
|
||||
//!
|
||||
//! * Under `./node`, a `main.rs`, which is the point, and a `./service.rs`, which contains all the
|
||||
//! client side components. Skimming this file yields an overview of the networking, database,
|
||||
//! consensus and similar client side components.
|
||||
//!
|
||||
//! > The above two are conventions, not rules.
|
||||
//!
|
||||
//! ## Parachain?
|
||||
//!
|
||||
//! As noted above, Substrate is the main engine behind the Polkadot ecosystem. One of the ways
|
||||
//! through which Polkadot can be utilized is by building "parachains", blockchains that are
|
||||
//! connected to Polkadot's shared security.
|
||||
//!
|
||||
//! To build a parachain, one could use [`Cumulus`](https://github.com/paritytech/cumulus/), the
|
||||
//! library on top of Substrate, empowering any substrate-based chain to be a Polkadot parachain.
|
||||
//!
|
||||
//! ## Where To Go Next?
|
||||
//!
|
||||
//! Additional noteworthy crates within substrate:
|
||||
//!
|
||||
//! - RPC APIs of a Substrate node: [`sc-rpc-api`]/[`sc-rpc`]
|
||||
//! - CLI Options of a Substrate node: [`sc-cli`]
|
||||
//! - All of the consensus related crates provided by Substrate:
|
||||
//! - [`sc-consensus-aura`]
|
||||
//! - [`sc-consensus-babe`]
|
||||
//! - [`sc-consensus-grandpa`]
|
||||
//! - [`sc-consensus-beefy`]
|
||||
//! - [`sc-consensus-manual-seal`]
|
||||
//! - [`sc-consensus-pow`]
|
||||
//!
|
||||
//! Additional noteworthy external resources:
|
||||
//!
|
||||
//! - [Substrate Developer Hub](https://substrate.dev)
|
||||
//! - [Parity Tech's Documentation Hub](https://paritytech.github.io/)
|
||||
//! - [Frontier: Substrate's Ethereum Compatibility Library](https://paritytech.github.io/frontier/)
|
||||
//! - [Polkadot Wiki](https://wiki.polkadot.network/en/)
|
||||
//!
|
||||
//! Notable upstream crates:
|
||||
//!
|
||||
//! - [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec)
|
||||
//! - [`parity-db`](https://github.com/paritytech/parity-db)
|
||||
//! - [`trie`](https://github.com/paritytech/trie)
|
||||
//! - [`parity-common`](https://github.com/paritytech/parity-common)
|
||||
//!
|
||||
//! Templates:
|
||||
//!
|
||||
//! - classic [`substrate-node-template`](https://github.com/substrate-developer-hub/substrate-node-template)
|
||||
//! - classic [cumulus-parachain-template](https://github.com/substrate-developer-hub/substrate-parachain-template)
|
||||
//! - [`extended-parachain-template`](https://github.com/paritytech/extended-parachain-template)
|
||||
//! - [`frontier-parachain-template`](https://github.com/paritytech/frontier-parachain-template)
|
||||
//!
|
||||
//! [polkadot]:
|
||||
//! https://img.shields.io/badge/polkadot-E6007A?style=for-the-badge&logo=polkadot&logoColor=white
|
||||
//! [github]:
|
||||
//! https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
|
||||
//! [`sp-io`]: ../sp_io/index.html
|
||||
//! [`sp-api`]: ../sp_api/index.html
|
||||
//! [`sp-api`]: ../sp_api/index.html
|
||||
//! [`sc-client-db`]: ../sc_client_db/index.html
|
||||
//! [`sc-network`]: ../sc_network/index.html
|
||||
//! [`sc-rpc-api`]: ../sc_rpc_api/index.html
|
||||
//! [`sc-rpc`]: ../sc_rpc/index.html
|
||||
//! [`sc-cli`]: ../sc_cli/index.html
|
||||
//! [`sc-consensus-aura`]: ../sc_consensus_aura/index.html
|
||||
//! [`sc-consensus-babe`]: ../sc_consensus_babe/index.html
|
||||
//! [`sc-consensus-grandpa`]: ../sc_consensus_grandpa/index.html
|
||||
//! [`sc-consensus-beefy`]: ../sc_consensus_beefy/index.html
|
||||
//! [`sc-consensus-manual-seal`]: ../sc_consensus_manual_seal/index.html
|
||||
//! [`sc-consensus-pow`]: ../sc_consensus_pow/index.html
|
||||
//! [`node`]: ../node_cli/index.html
|
||||
//! [`node-template`]: ../node_template/index.html
|
||||
//! [`kitchensink_runtime`]: ../kitchensink_runtime/index.html
|
||||
//! [`subkey`]: ../subkey/index.html
|
||||
//! [`chain-spec-builder`]: ../chain_spec_builder/index.html
|
||||
//! [`substrate-wasm-builder`]: https://crates.io/crates/substrate-wasm-builder
|
||||
|
||||
#![deny(rustdoc::broken_intra_doc_links)]
|
||||
#![deny(rustdoc::private_intra_doc_links)]
|
||||
|
||||
#[cfg_attr(doc, aquamarine::aquamarine)]
|
||||
/// In this module, we explore substrate at a more depth. First, let's establish substrate being
|
||||
/// divided into a client and runtime.
|
||||
///
|
||||
/// ```mermaid
|
||||
/// graph TB
|
||||
/// subgraph Substrate
|
||||
/// direction LR
|
||||
/// subgraph Client
|
||||
/// end
|
||||
/// subgraph Runtime
|
||||
/// end
|
||||
/// end
|
||||
/// ```
|
||||
///
|
||||
/// The client and the runtime of course need to communicate. This is done through two concepts:
|
||||
///
|
||||
/// 1. Host functions: a way for the (Wasm) runtime to talk to the client. All host functions are
|
||||
/// defined in [`sp-io`]. For example, [`sp-io::storage`] are the set of host functions that
|
||||
/// allow the runtime to read and write data to the on-chain state.
|
||||
/// 2. Runtime APIs: a way for the client to talk to the Wasm runtime. Runtime APIs are defined
|
||||
/// using macros and utilities in [`sp-api`]. For example, [`sp-api::Core`] is the most basic
|
||||
/// runtime API that any blockchain must implement in order to be able to (re) execute blocks.
|
||||
///
|
||||
/// ```mermaid
|
||||
/// graph TB
|
||||
/// subgraph Substrate
|
||||
/// direction LR
|
||||
/// subgraph Client
|
||||
/// end
|
||||
/// subgraph Runtime
|
||||
/// end
|
||||
/// Client --runtime-api--> Runtime
|
||||
/// Runtime --host-functions--> Client
|
||||
/// end
|
||||
/// ```
|
||||
///
|
||||
/// Finally, let's expand the diagram a bit further and look at the internals of each component:
|
||||
///
|
||||
/// ```mermaid
|
||||
/// graph TB
|
||||
/// subgraph Substrate
|
||||
/// direction LR
|
||||
/// subgraph Client
|
||||
/// Database
|
||||
/// Networking
|
||||
/// Consensus
|
||||
/// end
|
||||
/// subgraph Runtime
|
||||
/// subgraph FRAME
|
||||
/// direction LR
|
||||
/// Governance
|
||||
/// Currency
|
||||
/// Staking
|
||||
/// Identity
|
||||
/// end
|
||||
/// end
|
||||
/// Client --runtime-api--> Runtime
|
||||
/// Runtime --host-functions--> Client
|
||||
/// end
|
||||
/// ```
|
||||
///
|
||||
/// As noted the runtime contains all of the application specific logic of the blockchain. This is
|
||||
/// usually written with `FRAME`. The client, on the other hand, contains reusable and generic
|
||||
/// components that are not specific to one single blockchain, such as networking, database, and the
|
||||
/// consensus engine.
|
||||
///
|
||||
/// [`sp-io`]: ../../sp_io/index.html
|
||||
/// [`sp-api`]: ../../sp_api/index.html
|
||||
/// [`sp-io::storage`]: ../../sp_io/storage/index.html
|
||||
/// [`sp-api::Core`]: ../../sp_api/trait.Core.html
|
||||
pub mod substrate_diagram {}
|
||||
Reference in New Issue
Block a user